3

我正在使用 Sigar 获取应用程序服务器中当前正在运行的 JVM 的 CPU 使用率,并将其存储为该数据的历史视图,但我总是得到 0% 的 CPU 百分比。

同时,我打开我的visualVM 来监控CPU 使用率,我可以看到visualVM 中的CPU % 周期性变化,而它使用Sigar 总是报告0%。

这是我定期运行的代码:

Sigar sigar = new Sigar();
ProcCpu cpu = null;
long pId = sigar.getPid(); // This one gives me the same process ID that I see in visualVM
try {
    cpu = sigar.getProcCpu(pId);

} 
catch (SigarException se) {
    se.printStackTrace();
}
System.out.print(cpu.getPercent());

此代码始终给出 0%。

在这种情况下我做错了什么?如何让 Sigar 显示类似于 VisualVM 中显示的 CPU 使用率?

我尝试添加

cpu.gather(sigar, pId);

在调用 getProcCpu(pid) 之后,即使我不断增加和减少服务器上的负载,我也只能得到两个值(0.0 和 9.08729312E-315)......

4

1 回答 1

6

我认为这取决于 Sigar 如何解释可用信息。它可用的信息(CPU 使用时间)更新不频繁,ProcCpu只是一个即时进程 CPU 使用信息,这就是为什么大多数 CPU 使用为ProcCpu0。从未见过它们,但对于某些人来说,ProcCpu这个值应该大大优于 100 %。

您可以获取一段时间内的 CPU 使用情况,ProcCpu从它的开始和结束时刻分析两个 s,将 CPU 使用时间和ProcCpu(lastTime) 时间考虑在内。但请记住,CPU 使用时间值不会经常更新,因此有可能在ProcCpus 超过一秒的时间内获得相同的 CPU 使用时间。要获得实际的 CPU 使用信息,您必须收集两个或多个ProcCpus。


我绘制了一个监视器,它聚合和更新有关 CPU 使用率的信息:

import java.util.Timer;
import java.util.TimerTask;
import org.hyperic.sigar.ProcCpu;
import org.hyperic.sigar.Sigar;

class SigarLoadMonitor {

    private static final int TOTAL_TIME_UPDATE_LIMIT = 2000;

    private final Sigar sigar;
    private final int cpuCount;
    private final long pid;
    private ProcCpu prevPc;
    private double load;

    private TimerTask updateLoadTask = new TimerTask() {
        @Override public void run() {
            try {
                ProcCpu curPc = sigar.getProcCpu(pid);
                long totalDelta = curPc.getTotal() - prevPc.getTotal();
                long timeDelta = curPc.getLastTime() - prevPc.getLastTime();
                if (totalDelta == 0) {
                    if (timeDelta > TOTAL_TIME_UPDATE_LIMIT) load = 0;
                    if (load == 0) prevPc = curPc;
                } else {
                    load = 100. * totalDelta / timeDelta / cpuCount;
                    prevPc = curPc;
                }
            } catch (SigarException ex) {
                throw new RuntimeException(ex);
            }
        }
    };

    public SigarLoadMonitor() throws SigarException {
        sigar = new Sigar();
        cpuCount = sigar.getCpuList().length;
        pid = sigar.getPid();
        prevPc = sigar.getProcCpu(pid);
        load = 0;
        new Timer(true).schedule(updateLoadTask, 0, 1000);
    }

    public double getLoad() {
        return load;
    }
}
  • ProcCpu— 进程信息的即时 CPU 使用率
  • curPc.getTotal()— 进程使用 CPU 的总时间
  • curPc.getLastTime()ProcCpu—代表信息的时刻
  • CPU 使用率 ( load) 是进程在某个时期 ( totalDelta) 内使用 CPU 的时间与该时期的持续时间 ( timeDelta) 的比率。

虽然 CPU 使用时间不经常更新,但我引入了简单的启发式方法,假设负载与以前相同,而 CPU 使用时间不更新。但是假设某个进程在一段时间内可能是零负载,我引入了一个持续时间(TOTAL_TIME_UPDATE_LIMIT),之后相同的 CPU 使用时间值变得合法,并且假设负载真的为零。

于 2013-10-11T22:12:12.737 回答