sysinfo system call returns wrong load average values on linux
Asked Answered
M

1

8

I have a C program that prints some system statistics.

#include <sys/sysinfo.h>
#include <stdio.h>

int main() {
  int days, hours, mins;
  struct sysinfo sys_info;

  if(sysinfo(&sys_info) != 0)
    perror("sysinfo");

  // Uptime
  days = sys_info.uptime / 86400;
  hours = (sys_info.uptime / 3600) - (days * 24);
  mins = (sys_info.uptime / 60) - (days * 1440) - (hours * 60);

  printf("Uptime: %ddays, %dhours, %dminutes, %ldseconds\n",
                      days, hours, mins, sys_info.uptime % 60);

  // Load Averages for 1,5 and 15 minutes
  printf("Load Avgs: 1min(%ld) 5min(%ld) 15min(%ld)\n",
          sys_info.loads[0], sys_info.loads[1], sys_info.loads[2]);

  printf("Total Ram: %lluk\tFree: %lluk\n",
                sys_info.totalram *(unsigned long long)sys_info.mem_unit / 1024,
                sys_info.freeram *(unsigned long long)sys_info.mem_unit/ 1024);


  // Number of processes currently running.
  printf("Number of processes: %d\n", sys_info.procs);

  return 0;
}

My problem is that the load average values are different than /proc/loadavg

./a.out 
Uptime: 1days, 4hours, 1minutes, 16seconds
Load Avgs: 1min(13248) 5min(14880) 15min(11840)
Total Ram: 2052956k Free: 188104k
Number of processes: 265

Why? I am printing 13248 but "top" or "cat /proc/loadavg" gives 0.24. What is the problem?

Marquittamarr answered 14/2, 2011 at 14:14 Comment(2)
Would be useful to post the code that actually produced that output.Habiliment
sorry, I copied wrong file. Now is correctMarquittamarr
P
21

The call doesn't return the "wrong" values. Note that the type is integer, so it can't be intended to return the floating-point numbers printed by uptime.

See this thread for an investigation in how to interpret the returned values, and how to convert to the more familiar floats.

My guess (before reading the link) was that it's just represented as scaled up by 65,535 (216), and that seems to be what they found, too. So divide by 65536.0, or to be way cleaner (as pointed out in a comment) use the SI_LOAD_SHIFT constant and divide by (float)(1 << SI_LOAD_SHIFT).

Plaint answered 14/2, 2011 at 14:24 Comment(4)
In fact in <linux/kernel.h> there is #define SI_LOAD_SHIFT 16. Therefore you probably want to divide the load average by ((float)1<<SI_LOAD_SHIFT) rather than hardcoded 65536.Zicarelli
It would have been nice if the sysinfo man page documented this!Glowworm
More comprehensive answer here: https://mcmap.net/q/1323051/-can-not-understand-load-returned-by-sysinfo. You need to use both SI_LOAD_SHIFT and FSHIFTCorsetti
Actually perhaps I'm wrong, because dividing by 1<<SI_LOAD_SHIFT works on 4.9.113 and 5.4.15, but trying to use FSHIFT does not.Corsetti

© 2022 - 2024 — McMap. All rights reserved.