VMware Cloud Community
bcosta
Contributor
Contributor

sigar_cpu_get() separate values dont add to total bug?

I am using the C API, and on Windows 7 running a 32 bit binary, I call the sigar_cpu_get() a regular periods and compare the diffs. It turns out that the sum of the diffs dont add to the total. See below (Note I was expecting the idle value to be basically 0 in this test, at other times I have seen it with a non-zero value, but still things dont add up to the total):

188 + 1810 + 15 = 2013

This should equal the total: 2997 if my understanding of how this is supposted to work is correct.

For example:

----

At time t = 0:

----

user: 84704517

sys: 51951124

nice: 0

idle: 565436903

wait: 0

irq: 2154108

soft_irq: 0

stolen: 0

total: 1053139362

----

call t = 1sec

----

user: 84704705

sys: 51952934

nice: 0

idle: 565436903

wait: 0

irq: 2154123

soft_irq: 0

stolen: 0

total: 1053142359

diff user: 188 : 6.27294

diff sys: 1810 : 60.3937

diff nice: 0 : 0

diff idle: 0 : 0

diff wait: 0 : 0

diff irq: 15 : 0.500501

diff soft_irq: 0 : 0

diff stolen: 0 : 0

diff total: 2997

0 Kudos
2 Replies
bcosta
Contributor
Contributor

This is possibly my usage mistake. I may not have understood the purpose of this function. If i use the sigar_cpu_list_get() and sum the values across all CPU's the results turn out correct. It may be possible that sigar_cpu_get() returns not the summary for all CPU's but the value for the CPU calling the function right now. In which case this may be called by different CPU's one time after the other causing bad diffs in my case.

0 Kudos
klindsey
Contributor
Contributor

There is a bug in the sigar_cpu_get() function for windows.  Specifically, in win32_sigar.c the overall total is calculated incorrectly.  In the line below for calculating the total, a simple = should have been used instead of +=.  This will cause the reported total to be greatly exaggerated on a multiple processor machine.

static int sigar_cpu_ntsys_get(sigar_t *sigar, sigar_cpu_t *cpu)
{
    DWORD retval, num;
    int i;
    SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info[SPPI_MAX];
    /* into the lungs of hell */
    sigar_NtQuerySystemInformation(SystemProcessorPerformanceInformation,
                                   &info, sizeof(info), &retval);
    if (!retval) {
        return GetLastError();
    }
    num = retval/sizeof(info[0]);
    SIGAR_ZERO(cpu);
    for (i=0; i<num; i++) {
        cpu->idle += NS100_2MSEC(info[i].IdleTime.QuadPart);
        cpu->user += NS100_2MSEC(info[i].UserTime.QuadPart);
        cpu->sys  += NS100_2MSEC(info[i].KernelTime.QuadPart -
                                 info[i].IdleTime.QuadPart);
        cpu->irq  += NS100_2MSEC(info[i].InterruptTime.QuadPart);
        /* Should be cpu->total = cpu->idle + cpu->user + cpu->sys; */
        cpu->total += cpu->idle + cpu->user + cpu->sys;
    }
    return SIGAR_OK;
}

I've worked around by summing the idle, user and sys values in the calling code and ignoring the sigar provided total.

0 Kudos