vmstat: Use KiB instead of pages for paged in/out

While the kernel calls the fields pgpgin and pgpgout, the units
here are not pages, but KiB (or 2x 512 sectors).

The comments come from the referenced merged request, this commit fixes
the "vmstat -s lies" part:

https://elixir.bootlin.com/linux/v5.15-rc7/source/block/blk-core.c#L1057
has submit_bio() which includes the count_vm_events(PGPGIN, count) but what
is count? it is usually what bio_sectors() returns.

bio_sectors() is a macro in
https://elixir.bootlin.com/linux/v5.15-rc7/source/include/linux/bio.h#L49
that defines that as bio->bi_iter.bi_size >> 9. 2^9 is 512 or the sector
size. So our count is incremented by the number of 512-byte sectors.

As @dublio has already pointed out before this result is printed to vmstat,
it is /= 2 to give the number of kibibytes (as the sectors were 512 bytes,
we now made the block size 2*512 or 1024). The code even has
"sectors -> kbytes".

So unless there is something very strange going on, pgpgin and pgpgout in
/proc/vmstat return kibibytes.

What about pages (which is sort of implied in the name) or blocks (as
described on the man page)?

Pages can vary, but they are generally 4 KiB so they're out. That also means
vmstat -s lies :(

Blocks are harder to discount. While these too can vary, they can be 1 KiB;
they could also be something else (e.g dd its 512, filesystems 4096).
However, for memory management inside the kernel, there are sectors and
there are (near userland export) KiB, nothing else. It's probably more
accurate to say sectors are shifted in and out of block devices and the
kernel expresses these transfers to userland as KiB by halving the numbers.

What all this means is that using KiB for bi/bo aka pgpgin/pgpgout is more
accurate than saying blocks or pages.

Signed-off-by: Craig Small <csmall@dropbear.xyz>

References:
 procps-ng/procps!64
This commit is contained in:
Craig Small 2021-11-14 18:50:58 +11:00
parent 992a37e5ed
commit dae897b54d

View File

@ -890,8 +890,8 @@ static void sum_format(void)
printf(_("%13lld stolen cpu ticks\n"), TICv(sstat_STO)); printf(_("%13lld stolen cpu ticks\n"), TICv(sstat_STO));
printf(_("%13lld non-nice guest cpu ticks\n"), TICv(sstat_GST)); printf(_("%13lld non-nice guest cpu ticks\n"), TICv(sstat_GST));
printf(_("%13lld nice guest cpu ticks\n"), TICv(sstat_GNI)); printf(_("%13lld nice guest cpu ticks\n"), TICv(sstat_GNI));
printf(_("%13lu pages paged in\n"), VMSTAT_GET(vm_info, VMSTAT_PGPGIN, ul_int)); printf(_("%13lu K paged in\n"), VMSTAT_GET(vm_info, VMSTAT_PGPGIN, ul_int));
printf(_("%13lu pages paged out\n"), VMSTAT_GET(vm_info, VMSTAT_PGPGOUT, ul_int)); printf(_("%13lu K paged out\n"), VMSTAT_GET(vm_info, VMSTAT_PGPGOUT, ul_int));
printf(_("%13lu pages swapped in\n"), VMSTAT_GET(vm_info, VMSTAT_PSWPIN, ul_int)); printf(_("%13lu pages swapped in\n"), VMSTAT_GET(vm_info, VMSTAT_PSWPIN, ul_int));
printf(_("%13lu pages swapped out\n"), VMSTAT_GET(vm_info, VMSTAT_PSWPOUT, ul_int)); printf(_("%13lu pages swapped out\n"), VMSTAT_GET(vm_info, VMSTAT_PSWPOUT, ul_int));
printf(_("%13lu interrupts\n"), SYSv(sstat_INT)); printf(_("%13lu interrupts\n"), SYSv(sstat_INT));