Search code examples
javacpupercentagezerosigar

Sigar ProcCpu gather method always returns 0 for percentage value


I'm using Sigar to try and get the CPU and memory usage of individual processes (under Windows). I am able to get these stats correctly for the system as a whole with the below code :

Sigar sigar = new Sigar();

long totalMemory = sigar.getMem().getTotal() / 1024 /1024;
model.addAttribute("totalMemory", totalMemory);

double usedPercentage = sigar.getMem().getUsedPercent();
model.addAttribute("usedPercentage", String.format( "%.2f", usedPercentage));

double freePercentage = sigar.getMem().getFreePercent();
model.addAttribute("freePercentage", String.format( "%.2f", freePercentage));

double cpuUsedPercentage = sigar.getCpuPerc().getCombined() * 100;
model.addAttribute("cpuUsedPercentage", String.format( "%.2f", cpuUsedPercentage));

This displays the following quite nicely in my web page :

Total System Memory : 16289 MB Used Memory Percentage : 66.81 % Free Memory Percentage : 33.19 % CPU Usage : 30.44 %

Now I'm trying to get info from individual processes such as Java and SQL Server and, while the memory is correctly gathered, the CPU usage for both processes is ALWAYS 0. Below is the code I'm using :

Sigar sigar = new Sigar();
List<ProcessInfo> processes = new ArrayList<>();

ProcessFinder processFinder = new ProcessFinder(sigar);
long[] javaPIDs = null;
Long sqlPID = null;

try
{
    javaPIDs = processFinder.find("Exe.Name.ct=" + "java.exe");
    sqlPID = processFinder.find("Exe.Name.ct=" + "sqlservr.exe")[0];
}
catch (Exception ex)
{}

int i = 0;

while (i < javaPIDs.length)
{
    Long javaPID = javaPIDs[i];
    ProcessInfo javaProcess = new ProcessInfo();
    javaProcess.setPid(javaPID);
    javaProcess.setName("Java");

    ProcMem javaMem = new ProcMem();
    javaMem.gather(sigar, javaPID);
    javaProcess.setMemoryUsage(javaMem.getResident() / 1024 / 1024);

    MultiProcCpu javaCpu = new MultiProcCpu();
    javaCpu.gather(sigar, javaPID);
    javaProcess.setCpuUsage(String.format("%.2f", javaCpu.getPercent() * 100));

    processes.add(javaProcess);

    i++;
}

if (sqlPID != null)
{
    ProcessInfo sqlProcess = new ProcessInfo();
    sqlProcess.setPid(sqlPID);
    sqlProcess.setName("SQL Server");

    ProcMem sqlMem = new ProcMem();
    sqlMem.gather(sigar, sqlPID);

    sqlProcess.setMemoryUsage(sqlMem.getResident() / 1024 / 1024);

    ProcCpu sqlCpu = new MultiProcCpu();
    sqlCpu.gather(sigar, sqlPID);
    sqlProcess.setCpuUsage(String.format( "%.2f", sqlCpu.getPercent()));

    processes.add(sqlProcess);
}

model.addAttribute("processes", processes);

I have tried both ProcCpu and MultiProcCpu and both of them always return 0.0 even if I can see Java using 15% CPU in task manager. The documentation on the Sigar library is virtually non existent but the research i did tells me that i appear to be doing this correctly.

Does anyone know what I'm doing wrong?

Thanks!


Solution

  • I found the issue while continuing to search online. Basically, the sigar library can only retrieve the correct CPU values after a certain time. My issue is that i was initializing a new Sigar instance every time the page was displayed. I made my Sigar instance global to my Spring controller and now it returns correct percentages.