aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2026-01-19 02:16:10 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2026-01-19 02:16:10 +0100
commitafb92adf474bc313bad184ed1f3fee06455fb23f (patch)
tree4afa6d20b6720dfd992284bffb0e951ac826de7f
parentfd2ce3fa2710659721983ec06abb0252ffa086ea (diff)
downloadbusybox-w32-afb92adf474bc313bad184ed1f3fee06455fb23f.tar.gz
busybox-w32-afb92adf474bc313bad184ed1f3fee06455fb23f.tar.bz2
busybox-w32-afb92adf474bc313bad184ed1f3fee06455fb23f.zip
vmstat: smarter handling of header re-printing
function old new delta vmstat_main 230 559 +329 print_row 340 - -340 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/0 up/down: 329/-340) Total: -11 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--procps/vmstat.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/procps/vmstat.c b/procps/vmstat.c
index f479dbecf..79ee59b1e 100644
--- a/procps/vmstat.c
+++ b/procps/vmstat.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config VMSTAT 9//config:config VMSTAT
10//config: bool "vmstat (3 kb)" 10//config: bool "vmstat (2 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Report virtual memory statistics 13//config: Report virtual memory statistics
@@ -49,6 +49,8 @@ L("procs\0") "\2" L("r\0" )FROM_PROC_STAT M_DECREMENT "procs_running\
49 "\2" L("b\0" )FROM_PROC_STAT "procs_blocked\0" 49 "\2" L("b\0" )FROM_PROC_STAT "procs_blocked\0"
50L("memory\0") "\6" L("swpd\0" )FROM_PROC_MEMINFO PSEUDO_SWPD "\0" 50L("memory\0") "\6" L("swpd\0" )FROM_PROC_MEMINFO PSEUDO_SWPD "\0"
51 "\6" L("free\0" )FROM_PROC_MEMINFO "MemFree\0" 51 "\6" L("free\0" )FROM_PROC_MEMINFO "MemFree\0"
52//TODO? "MemAvailable" in newer kernels may be a more useful indicator how much memory is "free"
53//in the sense of being immediately availabe if allocation demand arises (e.g. by dropping cached filesystem data)
52 "\6" L("buff\0" )FROM_PROC_MEMINFO "Buffers\0" 54 "\6" L("buff\0" )FROM_PROC_MEMINFO "Buffers\0"
53 "\6" L("cache\0")FROM_PROC_MEMINFO PSEUDO_CACHE "\0" 55 "\6" L("cache\0")FROM_PROC_MEMINFO PSEUDO_CACHE "\0"
54L("swap\0") "\4" L("si\0" )FROM_PROC_VMSTAT M_DELTA "pswpin\0" 56L("swap\0") "\4" L("si\0" )FROM_PROC_VMSTAT M_DELTA "pswpin\0"
@@ -65,6 +67,8 @@ L("cpu\0") "\2" L("us\0" )FROM_PROC_STAT_CPU M_DPERCENT "\x0d" /* user
65// "gu"est columnt seems to be added in procps-ng 4.x.x (it makes the output not 80, but 83 chars): 67// "gu"est columnt seems to be added in procps-ng 4.x.x (it makes the output not 80, but 83 chars):
66 "\2" L("gu\0" )FROM_PROC_STAT_CPU M_DPERCENT "\x0c" /* guest */ 68 "\2" L("gu\0" )FROM_PROC_STAT_CPU M_DPERCENT "\x0c" /* guest */
67; 69;
70/* Number of columns defined in coldescs[] */
71#define NCOLS (2+4+2+2+2+6)
68/* Packed row data from coldescs[] is decoded into this structure */ 72/* Packed row data from coldescs[] is decoded into this structure */
69struct col { 73struct col {
70 L(const char *grplabel;) 74 L(const char *grplabel;)
@@ -78,13 +82,9 @@ struct col {
78#define MOD_DECREMENT 0x04 82#define MOD_DECREMENT 0x04
79}; 83};
80 84
81/* Number of columns defined in coldescs[] */
82#define NCOLS (2+4+2+2+2+6)
83
84/* Globals. Sort by size and access frequency. */
85struct globals { 85struct globals {
86 unsigned data1[NCOLS]; 86 unsigned data[NCOLS];
87 unsigned data2[NCOLS]; 87 unsigned prev[NCOLS];
88}; 88};
89#define G (*(struct globals*)bb_common_bufsiz1) 89#define G (*(struct globals*)bb_common_bufsiz1)
90#define INIT_G() do { \ 90#define INIT_G() do { \
@@ -419,7 +419,6 @@ static void print_header(void)
419#if FIXED_HEADER 419#if FIXED_HEADER
420 /* The header is constant yet and can be hardcoded instead, 420 /* The header is constant yet and can be hardcoded instead,
421 * but adding options such as -wtd to match upstream will change that */ 421 * but adding options such as -wtd to match upstream will change that */
422//TODO: remove grplabel/label from coldescs[], they are unused
423 puts( 422 puts(
424"procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------""\n" 423"procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------""\n"
425" r b swpd free buff cache si so bi bo in cs us sy id wa st gu" 424" r b swpd free buff cache si so bi bo in cs us sy id wa st gu"
@@ -480,16 +479,18 @@ int vmstat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
480int vmstat_main(int argc UNUSED_PARAM, char **argv) 479int vmstat_main(int argc UNUSED_PARAM, char **argv)
481{ 480{
482 int opt; 481 int opt;
483 unsigned interval = 0; 482 unsigned interval;
484 int count = 1; 483 int count;
485 unsigned height; 484 unsigned height;
486 unsigned rows; 485 int row;
487 486
488 INIT_G(); 487 INIT_G();
489 488
490 /* Parse and process arguments */ 489 /* Parse and process arguments */
491 opt = getopt32(argv, "n"); 490 opt = getopt32(argv, "n");
492 argv += optind; 491 argv += optind;
492 interval = 0;
493 count = 1;
493 if (*argv) { 494 if (*argv) {
494 interval = xatoi_positive(*argv); 495 interval = xatoi_positive(*argv);
495 count = (interval != 0 ? -1 : 1); 496 count = (interval != 0 ? -1 : 1);
@@ -500,23 +501,29 @@ int vmstat_main(int argc UNUSED_PARAM, char **argv)
500 501
501 /* Prepare to re-print the header row after it scrolls off */ 502 /* Prepare to re-print the header row after it scrolls off */
502 height = 0; 503 height = 0;
503 if (!(opt & OPT_n)) 504 if (!(opt & OPT_n)) {
504 get_terminal_width_height(STDOUT_FILENO, NULL, &height); 505 get_terminal_width_height(STDOUT_FILENO, NULL, &height);
506 /* match 4.0.4 behavior: re-print header if terminal has 4 or more lines */
507 height -= 3; /* can become zero or negative */
508 }
505 509
510 load_row(G.prev); /* prevents incorrect deltas in 1st sample */
511 row = 0;
506 /* Main loop */ 512 /* Main loop */
507 load_row(G.data1); /* prevents incorrect deltas in 1st sample */ 513 for (;;) {
508 for (rows = 0;; rows++) { 514 if (row == 0) {
509 if (rows == 0 || (height > 5 && (rows % (height - 3)) == 0))
510 print_header(); 515 print_header();
511 516 row = (int)height;
512 /* Flip between using data1/2 and data2/1 for old/new */
513 if (rows & 1) {
514 load_row(G.data1);
515 print_row(G.data1, G.data2);
516 } else {
517 load_row(G.data2);
518 print_row(G.data2, G.data1);
519 } 517 }
518 row--;
519 //if (row < 0) /* height <= 0: -n, or 3 or fewer lines in terminal */
520 // row = -1; /* do not count down, never become zero */
521 /* equivalent to above: */
522 row |= (row >> (sizeof(row)*8 - 1));
523
524 load_row(G.data);
525 print_row(G.data, G.prev);
526 memcpy(G.prev, G.data, sizeof(G.prev));
520 527
521 if (count > 0 && --count == 0) 528 if (count > 0 && --count == 0)
522 break; 529 break;