Skip to content

Commit

Permalink
vmstat: Rely on libxo for numbers humanization
Browse files Browse the repository at this point in the history
This makes code cleaner, plus fixes such nonsense as humanized JSON
and XML, making all numbers raw without quotes, spaces, suffixes, etc.

MFC after:      2 weeks
  • Loading branch information
amotin committed Dec 8, 2023
1 parent 181afaa commit 1f36ca5
Showing 1 changed file with 52 additions and 117 deletions.
169 changes: 52 additions & 117 deletions usr.bin/vmstat/vmstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ main(int argc, char *argv[])
if (argc < 0)
return (argc);

hflag = (xo_get_style(NULL) == XO_STYLE_TEXT) && isatty(1);
hflag = isatty(1);

while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:oPp:sw:z")) != -1) {
switch (c) {
Expand Down Expand Up @@ -282,6 +282,8 @@ main(int argc, char *argv[])
argv += optind;

xo_set_version(VMSTAT_XO_VERSION);
if (!hflag)
xo_set_options(NULL, "no-humanize");
if (todo == 0)
todo = VMSTAT;

Expand Down Expand Up @@ -626,23 +628,6 @@ getcpuinfo(u_long *maskp, int *maxidp)
*maxidp = maxid;
}


static void
prthuman(const char *name, uint64_t val, int size, int flags)
{
char buf[10];
char fmt[128];

snprintf(fmt, sizeof(fmt), "{:%s/%%*s}", name);

if (size < 5 || size > 9)
xo_errx(1, "doofus");
flags |= HN_NOSPACE | HN_DECIMAL;
humanize_number(buf, size, val, "", HN_AUTOSCALE, flags);
xo_attr("value", "%ju", (uintmax_t) val);
xo_emit(fmt, size, buf);
}

static void
dovmstat(unsigned int interval, int reps)
{
Expand Down Expand Up @@ -769,27 +754,13 @@ dovmstat(unsigned int interval, int reps)
total.t_pw, total.t_sw);
xo_close_container("processes");
xo_open_container("memory");
#define vmstat_pgtok(a) ((uintmax_t)(a) * (sum.v_page_size >> 10))
#define rate(x) (unsigned long)(((x) * rate_adj + halfuptime) / uptime)
if (hflag) {
prthuman("available-memory",
total.t_avm * (uint64_t)sum.v_page_size, 5, HN_B);
prthuman("free-memory",
total.t_free * (uint64_t)sum.v_page_size, 5, HN_B);
prthuman("total-page-faults",
rate(sum.v_vm_faults - osum.v_vm_faults), 5, 0);
xo_emit(" ");
} else {
xo_emit(" ");
xo_emit("{:available-memory/%7ju}",
vmstat_pgtok(total.t_avm));
xo_emit(" ");
xo_emit("{:free-memory/%7ju}",
vmstat_pgtok(total.t_free));
xo_emit(" ");
xo_emit("{:total-page-faults/%5lu} ",
rate(sum.v_vm_faults - osum.v_vm_faults));
}
xo_emit(" {[:4}{h,hn-decimal:available-memory/%ju}{]:}",
(uintmax_t)total.t_avm * sum.v_page_size);
xo_emit(" {[:4}{h,hn-decimal:free-memory/%ju}{]:}",
(uintmax_t)total.t_free * sum.v_page_size);
xo_emit(" {[:4}{h,hn-decimal,hn-1000:total-page-faults/%lu}{]:} ",
rate(sum.v_vm_faults - osum.v_vm_faults));
xo_close_container("memory");

xo_open_container("paging-rates");
Expand All @@ -801,38 +772,20 @@ dovmstat(unsigned int interval, int reps)
xo_emit("{:paged-out/%3lu}",
rate(sum.v_swapout + sum.v_vnodeout -
(osum.v_swapout + osum.v_vnodeout)));
if (hflag) {
prthuman("freed",
rate(sum.v_tfree - osum.v_tfree), 5, 0);
prthuman("scanned",
rate(sum.v_pdpages - osum.v_pdpages), 5, 0);
} else {
xo_emit(" ");
xo_emit("{:freed/%5lu} ",
rate(sum.v_tfree - osum.v_tfree));
xo_emit("{:scanned/%4lu}",
rate(sum.v_pdpages - osum.v_pdpages));
}
xo_emit(" {[:4}{h,hn-decimal,hn-1000:freed/%lu}{]:}",
rate(sum.v_tfree - osum.v_tfree));
xo_emit(" {[:4}{h,hn-decimal,hn-1000:scanned/%lu}{]:}",
rate(sum.v_pdpages - osum.v_pdpages));
xo_close_container("paging-rates");

devstats();
xo_open_container("fault-rates");
if (hflag) {
prthuman("interrupts",
rate(sum.v_intr - osum.v_intr), 5, 0);
prthuman("system-calls",
rate(sum.v_syscall - osum.v_syscall), 5, 0);
prthuman("context-switches",
rate(sum.v_swtch - osum.v_swtch), 5, 0);
} else {
xo_emit(" ");
xo_emit("{:interrupts/%4lu} "
"{:system-calls/%5lu} "
"{:context-switches/%5lu}",
rate(sum.v_intr - osum.v_intr),
rate(sum.v_syscall - osum.v_syscall),
rate(sum.v_swtch - osum.v_swtch));
}
xo_emit(" {[:4}{h,hn-decimal,hn-1000:interrupts/%lu}{]:}"
" {[:4}{h,hn-decimal,hn-1000:system-calls/%lu}{]:}"
" {[:4}{h,hn-decimal,hn-1000:context-switches/%lu}{]:}",
rate(sum.v_intr - osum.v_intr),
rate(sum.v_syscall - osum.v_syscall),
rate(sum.v_swtch - osum.v_swtch));
xo_close_container("fault-rates");
if (Pflag)
pcpustats(cpumask, maxid);
Expand Down Expand Up @@ -863,10 +816,7 @@ printhdr(int maxid, u_long cpumask)
int i, num_shown;

num_shown = MIN(num_selected, maxshowdevs);
if (hflag)
xo_emit(" {T:procs} {T:memory} {T:/page%*s}", 19, "");
else
xo_emit("{T:procs} {T:memory} {T:/page%*s}", 19, "");
xo_emit(" {T:procs} {T:memory} {T:/page%*s}", 19, "");
if (num_shown > 1)
xo_emit(" {T:/disks %*s} ", num_shown * 5 - 7, "");
else if (num_shown == 1)
Expand All @@ -880,13 +830,8 @@ printhdr(int maxid, u_long cpumask)
xo_emit("\n");
} else
xo_emit(" {T:cpu}\n");
if (hflag) {
xo_emit(" {T:r} {T:b} {T:w} {T:avm} {T:fre} {T:flt} {T:re}"
" {T:pi} {T:po} {T:fr} {T:sr} ");
} else {
xo_emit("{T:r} {T:b} {T:w} {T:avm} {T:fre} {T:flt} "
"{T:re} {T:pi} {T:po} {T:fr} {T:sr} ");
}
xo_emit(" {T:r} {T:b} {T:w} {T:avm} {T:fre} {T:flt} {T:re}"
" {T:pi} {T:po} {T:fr} {T:sr} ");
for (i = 0; i < num_devices; i++)
if ((dev_select[i].selected) &&
(dev_select[i].selected <= maxshowdevs))
Expand Down Expand Up @@ -1146,64 +1091,53 @@ devstats(void)
xo_emit("{ekq:name/%s%d}",
dev_select[dn].device_name,
dev_select[dn].unit_number);
if (hflag) {
prthuman("transfers", (uint64_t)transfers_per_second,
5, HN_DIVISOR_1000);
} else {
xo_emit("{:transfers/%3.0Lf}", transfers_per_second);
}
xo_emit("{[:5}{h,hn-decimal,hn-1000:transfers/%ju}{]:}",
(uintmax_t)transfers_per_second);
xo_close_instance("device");
}
xo_close_list("device");
}

static void
percent(const char *name, double pctv, int *over)
percent(const char *name, long pctv, int *over)
{
int l;
char buf[10];
char fmt[128];

snprintf(fmt, sizeof(fmt), " {:%s/%%*s}", name);
l = snprintf(buf, sizeof(buf), "%.0f", pctv);
if (l == 1 && *over) {
xo_emit(fmt, 1, buf);
char fmt[64];

snprintf(fmt, sizeof(fmt), " {:%s/%%%ulld/%%lld}", name,
(*over && pctv <= 9) ? 1 : 2);
xo_emit(fmt, pctv);
if (*over && pctv <= 9)
(*over)--;
} else
xo_emit(fmt, 2, buf);
if (l > 2)
else if (pctv >= 100)
(*over)++;
}

static void
cpustats(void)
{
double lpct, total;
long total;
int state, over;

total = 0;
for (state = 0; state < CPUSTATES; ++state)
total += cur.cp_time[state];
if (total > 0)
lpct = 100.0 / total;
else
lpct = 0.0;
if (total == 0)
total = 1;
over = 0;
xo_open_container("cpu-statistics");
percent("user", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * lpct,
&over);
percent("system", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * lpct,
&over);
percent("idle", cur.cp_time[CP_IDLE] * lpct, &over);
percent("user", 100LL * (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) /
total, &over);
percent("system", 100LL * (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) /
total, &over);
percent("idle", 100LL * cur.cp_time[CP_IDLE] / total, &over);
xo_close_container("cpu-statistics");
}

static void
pcpustats(u_long cpumask, int maxid)
{
double lpct, total;
long tmp;
int i, over, state;
long tmp, total;
int i, state, over;

/* devstats does this for cp_time */
for (i = 0; i <= maxid; i++) {
Expand All @@ -1227,15 +1161,16 @@ pcpustats(u_long cpumask, int maxid)
total = 0;
for (state = 0; state < CPUSTATES; ++state)
total += cur_cp_times[i * CPUSTATES + state];
if (total)
lpct = 100.0 / total;
else
lpct = 0.0;
percent("user", (cur_cp_times[i * CPUSTATES + CP_USER] +
cur_cp_times[i * CPUSTATES + CP_NICE]) * lpct, &over);
percent("system", (cur_cp_times[i * CPUSTATES + CP_SYS] +
cur_cp_times[i * CPUSTATES + CP_INTR]) * lpct, &over);
percent("idle", cur_cp_times[i * CPUSTATES + CP_IDLE] * lpct,
if (total == 0)
total = 1;
percent("user",
100LL * (cur_cp_times[i * CPUSTATES + CP_USER] +
cur_cp_times[i * CPUSTATES + CP_NICE]) / total, &over);
percent("system",
100LL * (cur_cp_times[i * CPUSTATES + CP_SYS] +
cur_cp_times[i * CPUSTATES + CP_INTR]) / total, &over);
percent("idle",
100LL * cur_cp_times[i * CPUSTATES + CP_IDLE] / total,
&over);
xo_close_instance("cpu");
}
Expand Down

0 comments on commit 1f36ca5

Please sign in to comment.