2013-10-11 38 views
2

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

与此同时,我保持visualVM打开以监视CPU使用情况,并且我看到CPU使用visualVM定期更改,而它总是使用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显示CPU使用情况,类似于VisualVM中显示的使用情况?

我打过电话后getProcCpu(PID)加入

cpu.gather(sigar, pId); 

,但我不断收到只有两个值(0.0和9.08729312E-315),即使我不停的增长和服务器上的负荷...

回答

6

我认为这取决于Sigar如何解释可用信息。可用的信息(CPU使用时间)更新不是很经常,而且ProcCpu只是一个即时进程CPU使用率信息,这就是为什么大多数ProcCpu的CPU使用率为0.从未看过它们,但对于某些ProcCpu这个值应该是很大的优于100%。

您可能会在某段时间内获取CPU使用量,从开始和结束时刻分析两个ProcCpu s,并将CPU使用时间和时间考虑在内,将ProcCpu(lastTime)占用。但请记住,CPU使用时间值的更新不是很频繁,因此可能会得到相同的CPU使用时间ProcCpu s。要获得实际的CPU使用率信息,您必须收集两个或更多个ProcCpu


心中已经勾勒其上的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使用时间值变为合法,并且假设负载确实为零。

+0

谢谢你!顺便说一句,'TOTAL_TIME_UPDATE_LIMIT'应该至少1秒? – Alvaro

+0

@Alvaro不需要。它取决于目标参数真正更新的频率。如果您将“TOTAL_TIME_UPDATE_LIMIT”设置得太低,则会在输出中看到类似saw功能的内​​容。 –

+0

我怎么知道他们多久更新一次?现在我将它设置为1,并且我的值超过0. – Alvaro