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