Java 使用 Sigar API 获取 JVM CPU 使用率

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19323364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 16:06:11  来源:igfitidea点击:

Using Sigar API to get JVM CPU usage

javajvmcpu-usagevisualvmsigar

提问by Sammy

I'm using Sigar to get the CPU usage of the current running JVM in an application server and store it for historical view of this data, but I always get 0% CPU percentage.

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

In the meanwhile, I keep my visualVM open to monitor CPU usage, and I get to see the CPU % changing periodically in visualVM while it always reports 0% using Sigar.

与此同时,我让visualVM保持打开状态以监控CPU使用情况,我可以看到visualVM中的CPU百分比定期变化,而使用Sigar它总是报告0%。

Here is the code I m running periodically:

这是我定期运行的代码:

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());

This code always gives 0%.

此代码始终给出 0%。

What am I doing wrong it this case? How can I get Sigar to display CPU usage similar to the usage displayed in VisualVM?

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

I tried adding

我尝试添加

cpu.gather(sigar, pId);

after calling getProcCpu(pid), but I keep getting only two values (0.0 and 9.08729312E-315) even if I keep increasing and decreasing load on the server...

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

采纳答案by Timofey Gorshkov

I think that it depends on how Sigar interprets available information. Information available to it (CPU usage time) updates not very often, and ProcCpuis just an instant process CPU usage information, that is why CPU usage for most ProcCpuis 0. Never seen them, but for some ProcCputhis value should be be vastly superior to 100%.

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

You could get CPU usage for some period, analysing two ProcCpus from the start and the end moments of it, taking CPU usage time and time of ProcCpu(lastTime) into account. But remember, that CPU usage time value updates not very often, so it is possible to get the same CPU usage time for ProcCpus more than second apart. To have actual CPU usage information, you have to collect two or more ProcCpus.

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



I'v sketched a monitor that aggregates and updates information on CPU usage:

我绘制了一个监视器,用于汇总和更新有关 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— instant CPU usage by process information
  • curPc.getTotal()— total time that process used CPU
  • curPc.getLastTime()— moment for which ProcCpurepresents information
  • CPU usage (load) is a ratio of time that process used CPU during some period (totalDelta) and this period's duration (timeDelta).
  • ProcCpu— 通过进程信息即时 CPU 使用率
  • curPc.getTotal()— 进程使用 CPU 的总时间
  • curPc.getLastTime()ProcCpu代表信息的时刻
  • CPU 使用率 ( load) 是进程在某个时间段 ( totalDelta)内使用 CPU的时间与该时间段的持续时间 ( timeDelta) 之比。

While CPU usage time updates not very often, I've introdused simple heuristic, that supposes that the load is the same as previous, while CPU usage time doesn't update. But supposing that it could be zero load for a process for some time, I've introdused a duration (TOTAL_TIME_UPDATE_LIMIT), after which the same CPU usage time value become legal, and it is supposed that the load is really zero.

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