Использование Sigar API для получения загрузки процессора JVM

Я использую Sigar, чтобы получить информацию о загрузке ЦП текущей запущенной JVM на сервере приложений и сохранить ее для исторического просмотра этих данных, но я всегда получаю 0% загрузки ЦП.

В то же время я оставляю свой visualVM открытым для мониторинга использования ЦП, и я вижу, как периодически% CPU изменяется в visualVM, в то время как он всегда сообщает 0% с помощью Sigar.

Вот код, который я периодически запускаю:

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.gather(sigar, pId);

после вызова getProcCpu(pid), но я продолжаю получать только два значения (0.0 и 9.08729312E-315), даже если я продолжаю увеличивать и уменьшать нагрузку на сервер...

1 ответ

Решение

Я думаю, что это зависит от того, как Sigar интерпретирует имеющуюся информацию. Информация, доступная для него (время использования процессора) обновляется не очень часто, и ProcCpu это просто мгновенная информация об использовании процессора, поэтому использование процессора для большинства ProcCpu это 0. Никогда их не видел, но для некоторых ProcCpu это значение должно быть значительно выше 100%.

Вы могли бы получить использование процессора в течение некоторого периода, анализируя два ProcCpuот начала и до конца, принимая время загрузки процессора и время ProcCpu (lastTime) в учетную запись. Но помните, что значение времени использования ЦП обновляется не очень часто, поэтому можно получить то же время использования ЦП для ProcCpuс разницей больше чем на секунду. Чтобы иметь фактическую информацию об использовании процессора, вы должны собрать два или более ProcCpus.


Я набросал монитор, который собирает и обновляет информацию об использовании процессора:

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 - мгновенное использование процессора по информации о процессе
  • curPc.getTotal() - общее время, которое процесс использовал процессор
  • curPc.getLastTime() - момент, за который ProcCpu представляет информацию
  • Использование процессора (load) - отношение времени, в течение которого процесс использовал процессор в течение некоторого периода (totalDelta) и продолжительность этого периода (timeDelta).

Хотя время использования процессора обновляется не очень часто, я представил простую эвристику, которая предполагает, что нагрузка такая же, как и в предыдущем случае, а время использования процессора не обновляется. Но предположив, что это может быть нулевая загрузка для процесса в течение некоторого времени, я ввел продолжительность (TOTAL_TIME_UPDATE_LIMIT), после чего то же самое время использования ЦП становится допустимым, и предполагается, что нагрузка действительно равна нулю.

Другие вопросы по тегам