2

I want to calculate the current CPU core utilization on Linux from or .
Load average (getloadavg()) doesn't fit my purpose because it show only the whole CPU load with specific calculation.

Based on common sense I understand that the literally current CPU core load is either 0 or 100 percents. But I can calculate it in delta time.

From /proc/stat description I see the following metrics:

user: normal processes executing in user mode
nice: niced processes executing in user mode
system: processes executing in kernel mode
idle: twiddling thumbs
iowait: waiting for I/O to complete
irq: servicing interrupts
softirq: servicing softirqs

But I sill can't figure out how exactly to calculate CPU core load per second for example..
Sorry if obvious.

Related post: How can I determine the current CPU utilization from the shell?

NK-cell
  • 1,145
  • 6
  • 19
  • Does this help? https://stackoverflow.com/questions/65086372/c-parsing-proc-stat-to-calculate-current-cpu-usage-for-each-core?rq=1 – Aval Sarri Sep 19 '21 at 11:48
  • @AvalSarri Nope, this doesn't. There are only diffs (for the whole CPU string, not cores) for each of metrics I mentioned. But how these diffs are characterize the current CPU core utilization? – NK-cell Sep 19 '21 at 12:04
  • `the current CPU core utilization?` get utilization. Wait 1 second. Get utilization. Substract. `getloadavg()` does exactly the same, but inside kernel and with 1min/5min/15min periods. – KamilCuk Sep 19 '21 at 12:17
  • @KamilCuk `getloadavg()` has complex calculation and did not do it per core. I need the utilization of every CPU core. ***"Get utilization. Substract. "*** How can I get utilization? Seems that `/proc/stat` does not provide "utilization". Sorry I'm just a beginner – NK-cell Sep 19 '21 at 12:21
  • total time - idle time - iowait time is the active CPU time. Is that what you want? – stark Sep 19 '21 at 13:54
  • @stark Good question. Can these time metrics represent CPU load/utilization? I still don't understand it.. – NK-cell Sep 19 '21 at 14:17
  • @NK-cell They do. The time not spent idle is time spent doing work. 4th and 5th columns of each cpu row represent the total time spent idle and waiting on io for that particular cpu. – Kaihaku Sep 19 '21 at 14:22
  • `How can I get utilization?` From `/proc/stat`. The numbers literally represent time spend doing stuff. `Can these time metrics represent CPU load/utilization?` Everything / (idle+iowait) would be the percentage of time spend actually doing stuff. – KamilCuk Sep 19 '21 at 16:31
  • @Kaihaku Can you please provide a C example? – NK-cell Sep 19 '21 at 18:23
  • @KamilCuk *"The numbers literally represent time spend doing stuff."* Time in milliseconds? So if I have delta t = 1 sec, I must subtract the sum of metrics like: `free_time = 1000 - total_time - idle_time - iowait` and get the percentage of free time? – NK-cell Sep 19 '21 at 18:27
  • That's not relevant what the unit of time is, because you are going to divide them. But, anyway, it should be time in kernel ticks, usually 300hz. `get the percentage of free time?` You have to read the values, __wait__ 1 second, read values again and divide them. – KamilCuk Sep 19 '21 at 18:58

1 Answers1

2

The following program:

#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

struct cpuusage {
    char name[20];
    // Absolute values since last reboot.
    unsigned long long idletime;
    unsigned long long workingtime;
};

struct cpustat {
    char name[20];
    unsigned long long user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice;
};

struct cpuusage cpuusage_from_cpustat(struct cpustat s) {
    struct cpuusage r;
    strncpy(r.name, s.name, sizeof(r.name));
    r.name[sizeof(r.name) - 1] = '\0';
    r.idletime = s.idle + s.iowait;
    r.workingtime = s.user + s.nice + s.system + s.irq + s.softirq;
    return r;
}

void cpuusage_show_diff(struct cpuusage now, struct cpuusage prev) {
    // the number of ticks that passed by since the last measurement
    const unsigned long long workingtime = now.workingtime - prev.workingtime;
    const unsigned long long alltime = workingtime + (now.idletime - prev.idletime);
    // they are divided by themselves - so the unit does not matter.
    printf("Usage: %.0Lf%%\n", (long double)workingtime / alltime * 100.0L);
}

int main() {
    struct cpuusage prev = {0};
    //
    const int stat = open("/proc/stat", O_RDONLY);
    assert(stat != -1);
    fcntl(stat, F_SETFL, O_NONBLOCK);
    while (1) {
        // let's read everything in one call so it's nicely synced.
        int r = lseek(stat, SEEK_SET, 0);
        assert(r != -1);
        char buffer[10001];
        const ssize_t readed = read(stat, buffer, sizeof(buffer) - 1);
        assert(readed != -1);
        buffer[readed] = '\0';
        // Read the values from the readed buffer/
        FILE *f = fmemopen(buffer, readed, "r");
        // Uch, so much borign typing.
        struct cpustat c = {0};
        while (fscanf(f, "%19s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", c.name, &c.user, &c.nice,
                  &c.system, &c.idle, &c.iowait, &c.irq, &c.softirq, &c.steal, &c.guest,
                  &c.guest_nice) == 11) {
            // Just an example for first cpu core.
            if (strcmp(c.name, "cpu0") == 0) {
                struct cpuusage now = cpuusage_from_cpustat(c);
                cpuusage_show_diff(now, prev);
                prev = now;
                break;
            }
        }
        fclose(f);
        //
        sleep(1);
    }
}

Outputs the usage of the first core each second. I may be off with the calculations - consult this forum on which fields exactly to use from /dev/stat.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111