Hi, systat(1)'s vmstat view displays rates for things like interrupts. Strangely, it uses CPU time to compute these rates, not real time.
This is potentially misleading, particularly on an MP system. If I have 4 cores running on a HZ=100 kernel I expect ~400 clock interrupts per second. But systat(1) tells me I have 100 because we have 4 seconds worth of CPU time for every second of real time that elapses. I don't like it. I want to see how many interrupts there really were. This patch changes the vmstat view to use CLOCK_UPTIME to measure elapsed time and uses that when computing rates. The "Big Bar" is still drawn using CPU time, but for everything else I think you would want a rate based on the elapsed real time. Using CPU time isn't intuitive. We want CLOCK_UPTIME, not CLOCK_MONOTONIC, because we aren't interested in what the machine was doing when it was suspended. I have not changed dinfo() to keep the patch simple, but we should be using CLOCK_UPTIME there, too. Thoughts? Index: vmstat.c =================================================================== RCS file: /cvs/src/usr.bin/systat/vmstat.c,v retrieving revision 1.91 diff -u -p -r1.91 vmstat.c --- vmstat.c 28 Jun 2019 13:35:04 -0000 1.91 +++ vmstat.c 16 Sep 2020 03:56:14 -0000 @@ -320,7 +320,7 @@ labelkre(void) #define PUTRATE(fld, l, c, w) \ do { \ Y(fld); \ - putint((int)((float)s.fld/etime + 0.5), l, c, w); \ + putint((int)((float)s.fld / eruntime + 0.5), l, c, w); \ } while (0) #define MAXFAIL 5 @@ -330,12 +330,18 @@ static char cpuorder[] = { CP_INTR, CP_S void showkre(void) { + static struct timespec prev; + struct timespec elapsed, now; float f1, f2; int psiz; u_int64_t inttotal, intcnt; int i, l, c; static int failcnt = 0, first_run = 0; - double etime; + double ecputime, eruntime; + + clock_gettime(CLOCK_UPTIME, &now); + timespecsub(&now, &prev, &elapsed); + prev = now; if (state == TIME) { if (!first_run) { @@ -343,12 +349,13 @@ showkre(void) return; } } - etime = 0; + eruntime = elapsed.tv_sec + elapsed.tv_nsec / 1000000000.0; + ecputime = 0; for (i = 0; i < CPUSTATES; i++) { X(cpustats.cs_time); - etime += s.cpustats.cs_time[i]; + ecputime += s.cpustats.cs_time[i]; } - if (etime < 5.0) { /* < 5 ticks - ignore this trash */ + if (ecputime < 5.0) { /* < 5 ticks - ignore this trash */ if (failcnt++ >= MAXFAIL) { error("The alternate system clock has died!"); failcnt = 0; @@ -356,12 +363,12 @@ showkre(void) return; } failcnt = 0; - etime /= hertz; + ecputime /= hertz; inttotal = 0; for (i = 0; i < nintr; i++) { t = intcnt = s.intrcnt[i]; s.intrcnt[i] -= s1.intrcnt[i]; - intcnt = (u_int64_t)((float)s.intrcnt[i]/etime + 0.5); + intcnt = (u_int64_t)((float)s.intrcnt[i] / eruntime + 0.5); inttotal += intcnt; if (intrloc[i] != 0) putuint64(intcnt, intrloc[i], INTSCOL, 8);