Download raw body.
systat(1): iostat: compute rates with elapsed time
In TIME mode, the iostat view sets etime to naptime before computing
rates. This is wrong. The elapsed time is never exactly naptime.
Instead, measure the real elapsed time between each print_io() call.
We need to read the clock during every call, regardless of mode,
because the mode can change between updates.
This patch also changes the iostat view's behavior during the first
update. During that first update, iostat has no prior data to use
when computing rates. Currently, the resulting output is "totals
since boot divided by naptime". Here's a concrete example:
$ systat -d1 io 1
DEVICE READ WRITE RTPS WTPS SEC
sd0 4544872K 7316640K 365102 687727 101.9
sd1 0 0 0 0 0.0
Totals 4544872K 7316640K 365102 687727 101.9
$ systat -d1 io 2
DEVICE READ WRITE RTPS WTPS SEC
sd0 2272436K 3658335K 182551 343866 50.9
sd1 0 0 0 0 0.0
Totals 2272436K 3658335K 182551 343866 50.9
$ systat -d io 0.5
DEVICE READ WRITE RTPS WTPS SEC
sd0 9089744K 14295M 730204 1376152 204.7
sd1 0 0 0 0 0.0
Totals 9089744K 14295M 730204 1376152 204.7
The second output is half the first (1 / 2). The third output is
twice the first (1 / 0.5). This is difficult to explain, let alone
document. The numbers are also meaningless.
IMHO, if we're going to print something during that first update, it
makes more sense to unconditionally set etime to 1.0 and print the
totals.
Thoughts? ok?
Index: iostat.c
===================================================================
RCS file: /cvs/src/usr.bin/systat/iostat.c,v
diff -u -p -r1.50 iostat.c
--- iostat.c 14 Aug 2021 14:22:26 -0000 1.50
+++ iostat.c 4 Apr 2024 19:15:29 -0000
@@ -166,13 +166,23 @@ read_io(void)
void
print_io(void)
{
+ static struct timespec prev;
+ struct timespec elapsed, now;
+ static int first = 1;
int n, count = 0;
int curr;
- if (state == BOOT)
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ if (first) {
+ first = 0;
etime = 1.0;
- else
- etime = naptime;
+ } else if (state == BOOT) {
+ etime = 1.0;
+ } else {
+ timespecsub(&now, &prev, &elapsed);
+ etime = elapsed.tv_sec + elapsed.tv_nsec / 1000000000.0;
+ }
+ prev = now;
/* XXX engine internals: save and restore curr_line for bcache */
curr = curr_line;
systat(1): iostat: compute rates with elapsed time