3

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.

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.

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%.

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

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...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sammy
  • 4,538
  • 8
  • 33
  • 52

1 Answers1

6

I think that it depends on how Sigar interprets available information. Information available to it (CPU usage time) updates not very often, and ProcCpu is just an instant process CPU usage information, that is why CPU usage for most ProcCpu is 0. Never seen them, but for some ProcCpu this value should be be vastly superior to 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.


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

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 ProcCpu represents information
  • CPU usage (load) is a ratio of time that process used CPU during some period (totalDelta) and this period's duration (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.

Timofey Gorshkov
  • 4,987
  • 6
  • 41
  • 66
  • Thanks man! By the way, `TOTAL_TIME_UPDATE_LIMIT` should be at least 1 second? – Alvaro Mar 07 '14 at 11:47
  • @Alvaro No. It depends on how often the target parameters really updates. If you set `TOTAL_TIME_UPDATE_LIMIT` too low, you'll get something like saw function in the output. – Timofey Gorshkov Mar 07 '14 at 15:10
  • how can I know how often do they get updated then? Right now I set it to 1 and I'm getting values over 0. – Alvaro Mar 07 '14 at 15:13
  • This question is out of my competiotion… – Timofey Gorshkov Mar 07 '14 at 20:44
  • What do you mean with that? I just dont know what you mean when you say "it depends on how of the the target parameters really updates". The process data you mean? How can I get that value then? How did you make it work if you dont know how to get it? – Alvaro Mar 13 '14 at 17:02
  • Also, shouldn't the `load = 100. * totalDelta / timeDelta / cpuCount;` be an absolute value ? Sometimes I'm getting negative data. – Alvaro Mar 14 '14 at 10:38
  • Unfortunately my answer totally based on experiments on Sigar and I don't know it's internal design, so I couldn't answer your questions… – Timofey Gorshkov Mar 14 '14 at 11:27
  • Did you had any trouble with this? Sometimes, randomly, I'm getting values over 100%, such as 4489. I'm using you script so do you know why is this happening? – Alvaro Jun 12 '14 at 10:50
  • Would it be ok if I set `TOTAL_TIME_UPDATE_LIMIT` to `1`? – Alvaro Jun 12 '14 at 10:55
  • "but for some ProcCpu this value should be be vastly superior to 100%." How can it be superior to 100% ? – Alvaro Oct 23 '15 at 09:05