我认为这取决于 Sigar 如何解释可用信息。它可用的信息(CPU 使用时间)更新不频繁,ProcCpu
只是一个即时进程 CPU 使用信息,这就是为什么大多数 CPU 使用为ProcCpu
0。从未见过它们,但对于某些人来说,ProcCpu
这个值应该大大优于 100 %。
您可以获取一段时间内的 CPU 使用情况,ProcCpu
从它的开始和结束时刻分析两个 s,将 CPU 使用时间和ProcCpu
(lastTime) 时间考虑在内。但请记住,CPU 使用时间值不会经常更新,因此有可能在ProcCpu
s 超过一秒的时间内获得相同的 CPU 使用时间。要获得实际的 CPU 使用信息,您必须收集两个或多个ProcCpu
s。
我绘制了一个监视器,它聚合和更新有关 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 使用时间值变得合法,并且假设负载真的为零。