SIGAR的getprocmem与getproccpu输出解析及代码放置位置咨询
关于SIGAR获取Java单个函数资源消耗的问题解答
一、先搞懂getprocmem()和getproccpu()的输出单位
从你提供的Procinfo截图来看,里面的单位是本地化后的友好缩写:
- ko:对应英文的
kB(千字节),也就是1024字节 - Mo:对应英文的
MB(兆字节),也就是1024千字节(1,048,576字节)
具体到两个方法的返回对象,我再拆解下核心字段的含义和单位:
1. getprocmem(pid)返回的ProcMem对象
它的所有内存字段本质单位都是字节,截图里是为了可读性做了换算:
getRss():进程当前占用的常驻物理内存(Resident Set Size),截图里的Mem列就是这个值转成ko/Mo后的结果getSize():进程的虚拟内存总大小,包含物理内存、交换分区和未实际使用的内存页getShare():进程与其他进程共享的内存大小
2. getproccpu(pid)返回的ProcCpu对象
它的时间类字段单位都是秒(支持小数位精确计算):
getUser():进程在用户态消耗的CPU时间getSys():进程在内核态消耗的CPU时间getTotal():用户态+内核态的总CPU时间,这是计算函数CPU消耗最常用的字段
二、如何放置方法才能获取单个函数的资源消耗
要精准拿到单个函数的资源消耗,必须做「前后差值对比」——因为SIGAR返回的是进程从启动到当前的累计资源使用量,直接取单次值根本反映不了目标函数的消耗。具体实现步骤如下:
1. 核心代码示例
import org.hyperic.sigar.Sigar; import org.hyperic.sigar.ProcMem; import org.hyperic.sigar.ProcCpu; public class FunctionResourceMonitor { public static void main(String[] args) throws Exception { // 初始化SIGAR(注意:Sigar是线程不安全的,建议单实例复用) try (Sigar sigar = new Sigar()) { long currentPid = sigar.getPid(); // ① 执行目标函数前,先获取基准资源数据 ProcMem preMem = sigar.getProcMem(currentPid); ProcCpu preCpu = sigar.getProcCpu(currentPid); // ② 调用你要监控的目标函数 yourTargetBusinessFunction(); // ③ 函数执行完成后,获取最新资源数据 ProcMem postMem = sigar.getProcMem(currentPid); ProcCpu postCpu = sigar.getProcCpu(currentPid); // ④ 计算差值——这才是目标函数真正消耗的资源 long usedMemKB = (postMem.getRss() - preMem.getRss()) / 1024; // 转成KB方便阅读 double usedCpuSeconds = postCpu.getTotal() - preCpu.getTotal(); System.out.println("目标函数消耗内存:" + usedMemKB + " KB"); System.out.println("目标函数消耗CPU时间:" + usedCpuSeconds + " 秒"); } } // 你要监控的目标业务函数 private static void yourTargetBusinessFunction() { // 这里放你的实际业务逻辑,比如复杂计算、文件IO、数据库操作等 for (int i = 0; i < 1000000; i++) { Math.pow(i, 3); } } }
2. 关键注意事项
- 隔离干扰:如果你的程序是多线程架构,其他线程的资源消耗会干扰差值结果。建议在单独线程中执行目标函数,或者在测试环境中单独运行这段监控代码。
- 短函数优化:如果目标函数执行时间极短(比如几毫秒),单次差值误差会很大,可以循环执行目标函数多次(比如1000次),然后取平均消耗值。
- 资源释放:Sigar依赖本地系统库,一定要用
try-with-resources或者手动调用sigar.close()释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者wink peace
相关产品推荐
相关产品推荐

