landley / toybox

toybox
http://landley.net/toybox
BSD Zero Clause License
2.43k stars 338 forks source link

vmstat block io read/write is incorrect #525

Open arthurpi opened 1 day ago

arthurpi commented 1 day ago

On version 0.8.10 (haven't tested master but code seems to be the same)

The block input and output rates are computed using pgpgin and pgpgout from /proc/vmstat: https://github.com/landley/toybox/blob/0.8.10/toys/other/vmstat.c#L50

We then multiply these diffs in pgpgin pgpgout by the page size (to get a value in Kibibyte/s) https://github.com/landley/toybox/blob/0.8.10/toys/other/vmstat.c#L142

This is not very accurate, seems like writing any amount of bytes will always be computed as at least _SC_PAGESIZE (commonly 4096 bytes, but it will be even worse on 16KB page systems).

As an experiment, we've tested writing 1GB to a file, using a ~100MB/s disk, and the rates vmstat reported were impossible (about 300MB/s).

The --help message is also not using the correct unit:

..., file disk blocks input and output per second ...

Whereas the actual value is computed in Kibibyte/s and not in disk block size per second.

I looked at procps-ng vmstat implementation, they are using /proc/diskstats: https://gitlab.com/procps-ng/procps/-/blob/master/library/diskstats.c#L511

Could we use /proc/diskstats here as well?

Happy to contribute to a fix, but I would like to get an expert's opinion first.

Cheers!

arthurpi commented 1 day ago

Oh, I also just realized something. The pgpgin and pgpgout from /proc/vmstat are in KB units, not page unit. Tested on my linux 6.9 machine, by doing

$ grep pgpgout /proc/vmstat
pgpgout 1199848609
$ dd if=/dev/random of=dump.img bs=1M count=10000  # wrote 10GB to disk
$ grep pgpgout /proc/vmstat
pgpgout 1209812241
$ echo "1209812241-1199848609" | bc
9963632

9,963,632 KB -> that's the 10GB I wrote

landley commented 1 day ago

I'm not really a vmstat user, so I dunno what success looks like here. If you have a proposed fix I'm happy to take a look.