xref: /aosp_15_r20/external/toybox/toys/other/vmstat.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* vmstat.c - Report virtual memory statistics.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2012 Elie De Brauwer <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  *
5*cf5a6c84SAndroid Build Coastguard Worker  * TODO: I have no idea how "system" category is calculated.
6*cf5a6c84SAndroid Build Coastguard Worker  * whatever we're doing isn't matching what other implementations are doing.
7*cf5a6c84SAndroid Build Coastguard Worker 
8*cf5a6c84SAndroid Build Coastguard Worker USE_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN|TOYFLAG_LINEBUF))
9*cf5a6c84SAndroid Build Coastguard Worker 
10*cf5a6c84SAndroid Build Coastguard Worker config VMSTAT
11*cf5a6c84SAndroid Build Coastguard Worker   bool "vmstat"
12*cf5a6c84SAndroid Build Coastguard Worker   default y
13*cf5a6c84SAndroid Build Coastguard Worker   help
14*cf5a6c84SAndroid Build Coastguard Worker     usage: vmstat [-n] [DELAY [COUNT]]
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker     Print virtual memory statistics, repeating each DELAY seconds, COUNT times.
17*cf5a6c84SAndroid Build Coastguard Worker     (With no DELAY, prints one line. With no COUNT, repeats until killed.)
18*cf5a6c84SAndroid Build Coastguard Worker 
19*cf5a6c84SAndroid Build Coastguard Worker     Show processes running and blocked, kilobytes swapped, free, buffered, and
20*cf5a6c84SAndroid Build Coastguard Worker     cached, kilobytes swapped in and out per second, file disk blocks input and
21*cf5a6c84SAndroid Build Coastguard Worker     output per second, interrupts and context switches per second, percent
22*cf5a6c84SAndroid Build Coastguard Worker     of CPU time spent running user code, system code, idle, and awaiting I/O.
23*cf5a6c84SAndroid Build Coastguard Worker     First line is since system started, later lines are since last line.
24*cf5a6c84SAndroid Build Coastguard Worker 
25*cf5a6c84SAndroid Build Coastguard Worker     -n	Display the header only once
26*cf5a6c84SAndroid Build Coastguard Worker */
27*cf5a6c84SAndroid Build Coastguard Worker 
28*cf5a6c84SAndroid Build Coastguard Worker #define FOR_vmstat
29*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
30*cf5a6c84SAndroid Build Coastguard Worker 
31*cf5a6c84SAndroid Build Coastguard Worker struct vmstat_proc {
32*cf5a6c84SAndroid Build Coastguard Worker   unsigned long long
33*cf5a6c84SAndroid Build Coastguard Worker     // From /proc/stat (jiffies) 0-10
34*cf5a6c84SAndroid Build Coastguard Worker     user, nice, sys, idle, wait, irq, sirq, intr, ctxt, running, blocked,
35*cf5a6c84SAndroid Build Coastguard Worker     // From /proc/meminfo (units are kb) 11-16
36*cf5a6c84SAndroid Build Coastguard Worker     memfree, buffers, cached, swapfree, swaptotal, reclaimable,
37*cf5a6c84SAndroid Build Coastguard Worker     // From /proc/vmstat (units are kb) 17-18
38*cf5a6c84SAndroid Build Coastguard Worker     io_in, io_out,
39*cf5a6c84SAndroid Build Coastguard Worker     // From /proc/vmstat (units are pages) 19-20
40*cf5a6c84SAndroid Build Coastguard Worker     swap_in, swap_out;
41*cf5a6c84SAndroid Build Coastguard Worker };
42*cf5a6c84SAndroid Build Coastguard Worker 
43*cf5a6c84SAndroid Build Coastguard Worker // All the elements of vmstat_proc are the same size, so we can populate it as
44*cf5a6c84SAndroid Build Coastguard Worker // a big array, then read the elements back out by name
get_vmstat_proc(struct vmstat_proc * vmsp)45*cf5a6c84SAndroid Build Coastguard Worker static void get_vmstat_proc(struct vmstat_proc *vmsp)
46*cf5a6c84SAndroid Build Coastguard Worker {
47*cf5a6c84SAndroid Build Coastguard Worker   char *vmstuff[] = { "/proc/stat", "cpu ", 0, 0, 0, 0, 0, 0, "intr ", "ctxt ",
48*cf5a6c84SAndroid Build Coastguard Worker     "procs_running ", "procs_blocked ", "/proc/meminfo", "MemFree:",
49*cf5a6c84SAndroid Build Coastguard Worker     "Buffers:", "Cached:", "SwapFree:", "SwapTotal:", "SReclaimable:",
50*cf5a6c84SAndroid Build Coastguard Worker     "/proc/vmstat", "pgpgin ", "pgpgout ", "pswpin ", "pswpout " };
51*cf5a6c84SAndroid Build Coastguard Worker   unsigned long long *new = (void *)vmsp;
52*cf5a6c84SAndroid Build Coastguard Worker   char *p = 0, *name = name, *file = 0;
53*cf5a6c84SAndroid Build Coastguard Worker   int i, j;
54*cf5a6c84SAndroid Build Coastguard Worker 
55*cf5a6c84SAndroid Build Coastguard Worker   // We use vmstuff to fill out vmstat_proc as an array of long long:
56*cf5a6c84SAndroid Build Coastguard Worker   //   Strings starting with / are the file to find next entries in
57*cf5a6c84SAndroid Build Coastguard Worker   //   Any other string is a key to search for, with decimal value right after
58*cf5a6c84SAndroid Build Coastguard Worker   //   0 means parse another value on same line as last key
59*cf5a6c84SAndroid Build Coastguard Worker 
60*cf5a6c84SAndroid Build Coastguard Worker   memset(new, 0, sizeof(struct vmstat_proc));
61*cf5a6c84SAndroid Build Coastguard Worker   for (i = j = 0; i<ARRAY_LEN(vmstuff); i++) {
62*cf5a6c84SAndroid Build Coastguard Worker     if (!vmstuff[i]) p++; // Read next entry on same line
63*cf5a6c84SAndroid Build Coastguard Worker     else if (*vmstuff[i] == '/') {
64*cf5a6c84SAndroid Build Coastguard Worker       free(file);
65*cf5a6c84SAndroid Build Coastguard Worker       file = xreadfile(name = vmstuff[i], 0, 0);
66*cf5a6c84SAndroid Build Coastguard Worker 
67*cf5a6c84SAndroid Build Coastguard Worker       continue;
68*cf5a6c84SAndroid Build Coastguard Worker     } else if (file && !(p = strafter(file, vmstuff[i]))) {
69*cf5a6c84SAndroid Build Coastguard Worker       free(file);
70*cf5a6c84SAndroid Build Coastguard Worker       file = 0;
71*cf5a6c84SAndroid Build Coastguard Worker     }
72*cf5a6c84SAndroid Build Coastguard Worker     if (!file) new++;
73*cf5a6c84SAndroid Build Coastguard Worker     else if (1==sscanf(p, "%llu%n", new++, &j)) p += j;
74*cf5a6c84SAndroid Build Coastguard Worker   }
75*cf5a6c84SAndroid Build Coastguard Worker   free(file);
76*cf5a6c84SAndroid Build Coastguard Worker 
77*cf5a6c84SAndroid Build Coastguard Worker   // combine some fields we display as aggregates
78*cf5a6c84SAndroid Build Coastguard Worker   vmsp->running--; // Don't include ourselves
79*cf5a6c84SAndroid Build Coastguard Worker   vmsp->user += vmsp->nice;
80*cf5a6c84SAndroid Build Coastguard Worker   vmsp->sys += vmsp->irq + vmsp->sirq;
81*cf5a6c84SAndroid Build Coastguard Worker   vmsp->swaptotal -= vmsp->swapfree;
82*cf5a6c84SAndroid Build Coastguard Worker   vmsp->cached += vmsp->reclaimable;
83*cf5a6c84SAndroid Build Coastguard Worker }
84*cf5a6c84SAndroid Build Coastguard Worker 
vmstat_main(void)85*cf5a6c84SAndroid Build Coastguard Worker void vmstat_main(void)
86*cf5a6c84SAndroid Build Coastguard Worker {
87*cf5a6c84SAndroid Build Coastguard Worker   int i, loop_delay = 0, loop_max = 0;
88*cf5a6c84SAndroid Build Coastguard Worker   unsigned loop, rows = 25, page_kb = sysconf(_SC_PAGESIZE)/1024;
89*cf5a6c84SAndroid Build Coastguard Worker   unsigned long long units, total_hz, *ptr, *oldptr;
90*cf5a6c84SAndroid Build Coastguard Worker   char *headers = "r\0b\0swpd\0free\0buff\0cache\0si\0so\0bi\0bo\0in\0cs\0us\0"
91*cf5a6c84SAndroid Build Coastguard Worker                   "sy\0id\0wa", lengths[] = {2,2,7,7,6,7,4,4,5,5,4,4,2,2,2,2};
92*cf5a6c84SAndroid Build Coastguard Worker 
93*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optc) loop_delay = atolx_range(toys.optargs[0], 0, INT_MAX);
94*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optc>1) loop_max = atolx_range(toys.optargs[1], 1, INT_MAX);
95*cf5a6c84SAndroid Build Coastguard Worker 
96*cf5a6c84SAndroid Build Coastguard Worker   xreadfile("/proc/uptime", toybuf, sizeof(toybuf));
97*cf5a6c84SAndroid Build Coastguard Worker   sscanf(toybuf, "%*s %llu", &units);
98*cf5a6c84SAndroid Build Coastguard Worker 
99*cf5a6c84SAndroid Build Coastguard Worker   for (loop = 0; !loop_max || loop<loop_max; loop++) {
100*cf5a6c84SAndroid Build Coastguard Worker     unsigned offset = 0, expected = 0;
101*cf5a6c84SAndroid Build Coastguard Worker 
102*cf5a6c84SAndroid Build Coastguard Worker     if (loop && loop_delay) sleep(loop_delay);
103*cf5a6c84SAndroid Build Coastguard Worker 
104*cf5a6c84SAndroid Build Coastguard Worker     ptr = oldptr = (void *)toybuf;
105*cf5a6c84SAndroid Build Coastguard Worker     *((loop&1) ? &ptr : &oldptr) += sizeof(struct vmstat_proc);
106*cf5a6c84SAndroid Build Coastguard Worker     get_vmstat_proc((void *)ptr);
107*cf5a6c84SAndroid Build Coastguard Worker 
108*cf5a6c84SAndroid Build Coastguard Worker     // Print headers
109*cf5a6c84SAndroid Build Coastguard Worker     if (rows>3 && !(loop % (rows-3))) {
110*cf5a6c84SAndroid Build Coastguard Worker       char *header = headers;
111*cf5a6c84SAndroid Build Coastguard Worker 
112*cf5a6c84SAndroid Build Coastguard Worker       if (!FLAG(n) && isatty(1)) terminal_size(0, &rows);
113*cf5a6c84SAndroid Build Coastguard Worker       else rows = 0;
114*cf5a6c84SAndroid Build Coastguard Worker 
115*cf5a6c84SAndroid Build Coastguard Worker       printf("procs ------------memory------------ ---swap-- -----io---- --system- ----cpu----\n");
116*cf5a6c84SAndroid Build Coastguard Worker       for (i = 0; i<sizeof(lengths); i++) {
117*cf5a6c84SAndroid Build Coastguard Worker         printf(" %*s"+!i, lengths[i], header);
118*cf5a6c84SAndroid Build Coastguard Worker         header += strlen(header)+1;
119*cf5a6c84SAndroid Build Coastguard Worker       }
120*cf5a6c84SAndroid Build Coastguard Worker       xputc('\n');
121*cf5a6c84SAndroid Build Coastguard Worker     }
122*cf5a6c84SAndroid Build Coastguard Worker 
123*cf5a6c84SAndroid Build Coastguard Worker     if (loop) units = loop_delay;
124*cf5a6c84SAndroid Build Coastguard Worker 
125*cf5a6c84SAndroid Build Coastguard Worker     // add up user, sys, idle, and wait time used since last time
126*cf5a6c84SAndroid Build Coastguard Worker     // (Already appended nice to user)
127*cf5a6c84SAndroid Build Coastguard Worker     for (i = total_hz = 0; i<4; i++) total_hz += ptr[i+!!i] - oldptr[i+!!i];
128*cf5a6c84SAndroid Build Coastguard Worker 
129*cf5a6c84SAndroid Build Coastguard Worker     // Output values in order[]: running, blocked, swaptotal, memfree, buffers,
130*cf5a6c84SAndroid Build Coastguard Worker     // cache, swap_in, swap_out, io_in, io_out, intr, ctxt, user, sys, idle,wait
131*cf5a6c84SAndroid Build Coastguard Worker 
132*cf5a6c84SAndroid Build Coastguard Worker     for (i=0; i<sizeof(lengths); i++) {
133*cf5a6c84SAndroid Build Coastguard Worker       char order[] = {9, 10, 15, 11, 12, 13, 19, 20, 17, 18, 7, 8, 0, 2, 3, 4};
134*cf5a6c84SAndroid Build Coastguard Worker       unsigned long long out = ptr[order[i]];
135*cf5a6c84SAndroid Build Coastguard Worker       int len;
136*cf5a6c84SAndroid Build Coastguard Worker 
137*cf5a6c84SAndroid Build Coastguard Worker       // Adjust rate and units
138*cf5a6c84SAndroid Build Coastguard Worker       if (i>5) out -= oldptr[order[i]];
139*cf5a6c84SAndroid Build Coastguard Worker       if (order[i]<7) out = ((out*100) + (total_hz/2)) / total_hz;
140*cf5a6c84SAndroid Build Coastguard Worker       else if (order[i]>16) {
141*cf5a6c84SAndroid Build Coastguard Worker         if (order[i]>18) out *= page_kb;
142*cf5a6c84SAndroid Build Coastguard Worker         out = (out*page_kb+(units-1))/units;
143*cf5a6c84SAndroid Build Coastguard Worker       } else if (order[i]<9) out = (out+(units-1)) / units;
144*cf5a6c84SAndroid Build Coastguard Worker 
145*cf5a6c84SAndroid Build Coastguard Worker       // If a field was too big to fit in its slot, try to compensate later
146*cf5a6c84SAndroid Build Coastguard Worker       expected += lengths[i] + !!i;
147*cf5a6c84SAndroid Build Coastguard Worker       len = expected - offset - !!i;
148*cf5a6c84SAndroid Build Coastguard Worker       if (len < 0) len = 0;
149*cf5a6c84SAndroid Build Coastguard Worker       offset += printf(" %*llu"+!i, len, out);
150*cf5a6c84SAndroid Build Coastguard Worker     }
151*cf5a6c84SAndroid Build Coastguard Worker     xputc('\n');
152*cf5a6c84SAndroid Build Coastguard Worker 
153*cf5a6c84SAndroid Build Coastguard Worker     if (!loop_delay) break;
154*cf5a6c84SAndroid Build Coastguard Worker   }
155*cf5a6c84SAndroid Build Coastguard Worker }
156