git: 473dc8e1ba2f - stable/14 - vmstat: Rely on libxo for numbers humanization

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Sat, 23 Dec 2023 04:33:55 UTC
The branch stable/14 has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=473dc8e1ba2fdcb080d1d3fccad72e97957ffc99

commit 473dc8e1ba2fdcb080d1d3fccad72e97957ffc99
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2023-12-08 02:21:35 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2023-12-23 04:13:24 +0000

    vmstat: Rely on libxo for numbers humanization
    
    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
    
    (cherry picked from commit 1f36ca5de596f7c2eb446df5b8e06877901d727a)
---
 usr.bin/vmstat/vmstat.c | 169 +++++++++++++++---------------------------------
 1 file changed, 52 insertions(+), 117 deletions(-)

diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c
index 6ef718864886..48da1343a71c 100644
--- a/usr.bin/vmstat/vmstat.c
+++ b/usr.bin/vmstat/vmstat.c
@@ -226,7 +226,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) {
@@ -295,6 +295,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;
 
@@ -639,23 +641,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)
 {
@@ -782,27 +767,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");
@@ -814,38 +785,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);
@@ -876,10 +829,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)
@@ -893,13 +843,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))
@@ -1159,64 +1104,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++) {
@@ -1240,15 +1174,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");
 	}