Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Potential iostat output format change



I find that I don't much like one aspect of the format of iostat -d
output, consider:

              wd0               wd1               wd4 
  KB/t  t/s  MB/s   KB/t  t/s  MB/s   KB/t  t/s  MB/s 
 15.98   18 0.286  14.26  871 12.13  14.22  853 11.84 
 0.000    0 0.000  0.000    0 0.000  0.000    0 0.000 
 0.000    0 0.000  0.500    0 0.000  0.500    0 0.000 
 0.000    0 0.000  0.000    0 0.000  0.000    0 0.000 
 0.000    0 0.000  0.000    0 0.000  0.000    0 0.000 
 0.000    0 0.000  0.000    0 0.000  0.000    0 0.000 

Notice how visually, that looks like one column, followed by two
groups of 3 columns, followed by another group of 2 columns.
In reality, of course, it is 3 groups of 3 columns, but the
leading white space in the t/s column makes that appear to be
a separator.

It seemed to me that just swapping the KB/t and t/s columns
would make that problem go away, so I did that - but then I
also noticed that 4 columns (plus one guaranteed blank) for
t/s is absurdly insufficient these days, I can get 15K t/s
on rotating rust without trying hard, easily 20K t/s on a
sata ssd, and 75K t/s on nvme.   That column needs more space,
so I did that as well.

The result is:

                wd0                 wd1                 wd4 
    t/s  KB/t  MB/s     t/s  KB/t  MB/s     t/s  KB/t  MB/s 
     18 15.98 0.286     869 14.26 12.09     850 14.22 11.81 
      0 0.000 0.000       0 0.000 0.000       0 0.000 0.000 
      0 0.000 0.000       0 0.000 0.000       0 0.000 0.000 
      0 0.000 0.000       0 0.000 0.000       0 0.000 0.000 
      0 0.000 0.000       0 0.000 0.000       0 0.000 0.000 
      0 0.000 0.000       0 0.000 0.000       0 0.000 0.000 

which to me just looks better, easier to spot the columns, and
more space for t/s (the decimal point moves around in the KB/t
and MB/s columns so they aren't as much of an issue).

Of course, once I did that, I had to look at the -D output, and
adjust that as well, and then modify both again when -I is included.
I won't bore you by showing the differences (but my guess is that
no-one has used -I in ages, its output columns were not nearly wide
enough for the info it was printing - give it a few drives, and the
headings would be on top of the wrong columns).

A patch which makes this happen is appended, for you to try.  This is
against HEAD, but iostat hasn't altered in ages, so it should apply
cleanly on -9, and perhaps -8 as well.

Note: it is not finished, I haven't (yet) done anything about the
code that works out how many drives there is space to display, which
definitely will need adjusting.  I also haven't fixed my other pet
hate, that it displays the drives in the order it finds them from
the kernel, rather than the order given on the command line (when
drives are specified there).   Further, with -I, the totals probably
need to auto-scale - now it simply always prints MB, which will result
in very bit numbers, quite quickly - I thought of having (per drive)
scaling apply each time the header lines are output - if the number
to be printed is getting too big for MB, switch to GB, and then TB, and ...
(systems which are up a long time can easily reach total transfer
volumes where counts even in TB start getting too big to manage).
(An additional option to show totals from when iostat starts, rather
than from boot, might also be useful).

Anyway, let me know what you think - is this worth finishing, or will
the changes break people's scripts (or something similar) - or do you
just prefer it the current way.

kre

Index: iostat.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/iostat/iostat.c,v
retrieving revision 1.67
diff -u -r1.67 iostat.c
--- iostat.c	8 Apr 2018 11:37:31 -0000	1.67
+++ iostat.c	6 Jun 2022 04:18:15 -0000
@@ -287,14 +287,20 @@
 
 	if (ISSET(todo, SHOW_STATS_1)) {
 		for (i = 0; i < ndrive; i++)
-			if (cur.select[i])
-				(void)printf("        %9.9s ", cur.name[i]);
+			if (cur.select[i]) {
+				if (ISSET(todo, SHOW_TOTALS))
+					(void)printf("    ");
+				(void)printf("          %9.9s ", cur.name[i]);
+			}
 	}
 
 	if (ISSET(todo, SHOW_STATS_2)) {
 		for (i = 0; i < ndrive; i++)
-			if (cur.select[i])
-				(void)printf("        %9.9s ", cur.name[i]);
+			if (cur.select[i]) {
+				if (ISSET(todo, SHOW_TOTALS))
+					(void)printf("           ");
+				(void)printf("          %9.9s ", cur.name[i]);
+			}
 	}
 
 	if (ISSET(todo, SHOW_CPU))
@@ -310,16 +316,20 @@
 		for (i = 0; i < ndrive; i++)
 			if (cur.select[i]) {
 				if (ISSET(todo, SHOW_TOTALS))
-					(void)printf("  KB/t  xfr  MB   ");
+					(void)printf("      xfr  KB/t      MB ");
 				else
-					(void)printf("  KB/t  t/s  MB/s ");
+					(void)printf("    t/s  KB/t  MB/s ");
 			}
 	}
 
 	if (ISSET(todo, SHOW_STATS_2)) {
 		for (i = 0; i < ndrive; i++)
-			if (cur.select[i])
-				(void)printf("    KB   xfr time ");
+			if (cur.select[i]) {
+				if (ISSET(todo, SHOW_TOTALS))
+					(void)printf("       xfr          KB    time ");
+				else
+					(void)printf("    xfr    KB  time ");
+			}
 	}
 
 	if (ISSET(todo, SHOW_CPU))
@@ -346,6 +356,12 @@
 {
 	size_t dn;
 	double atime, dtime, mbps;
+	int c1, c2, c3;
+
+	if (ISSET(todo, SHOW_TOTALS))
+		c1 = 8, c2 = 5, c3 = 7;		/* mucho magico */
+	else
+		c1 = 6, c2 = 5, c3 = 5;		/* and moreso */
 
 	for (dn = 0; dn < ndrive; ++dn) {
 		if (!cur.select[dn])
@@ -353,19 +369,19 @@
 
 		dtime = drive_time(etime, dn);
 
+					/* average transfers per second. */
+		(void)printf(" %*.0f", c1,
+		    (cur.rxfer[dn] + cur.wxfer[dn]) / dtime);
+
 					/* average Kbytes per transfer. */
 		if (cur.rxfer[dn] + cur.wxfer[dn])
 			mbps = ((cur.rbytes[dn] + cur.wbytes[dn]) /
 			    1024.0) / (cur.rxfer[dn] + cur.wxfer[dn]);
 		else
 			mbps = 0.0;
-		(void)printf(" %5.*f",
+		(void)printf(" %*.*f", c2,
 		    MAX(0, 3 - (int)floor(log10(fmax(1.0, mbps)))), mbps);
 
-					/* average transfers per second. */
-		(void)printf(" %4.0f",
-		    (cur.rxfer[dn] + cur.wxfer[dn]) / dtime);
-
 					/* time busy in drive activity */
 		atime = (double)cur.time[dn].tv_sec +
 		    ((double)cur.time[dn].tv_usec / (double)1000000);
@@ -377,7 +393,7 @@
 		else
 			mbps = 0;
 		mbps /= dtime;
-		(void)printf(" %5.*f ",
+		(void)printf(" %*.*f ", c3,
 		    MAX(0, 3 - (int)floor(log10(fmax(1.0, mbps)))), mbps);
 	}
 }
@@ -387,6 +403,12 @@
 {
 	size_t dn;
 	double atime, dtime;
+	int c1, c2, c3;
+
+	if (ISSET(todo, SHOW_TOTALS))
+		c1 = 9, c2 = 11, c3 = 7;		/* also magico */
+	else
+		c1 = 6, c2 = 5, c3 = 5;		/* even moreso */
 
 	for (dn = 0; dn < ndrive; ++dn) {
 		if (!cur.select[dn])
@@ -394,18 +416,18 @@
 
 		dtime = drive_time(etime, dn);
 
-					/* average kbytes per second. */
-		(void)printf(" %5.0f",
-		    (cur.rbytes[dn] + cur.wbytes[dn]) / 1024.0 / dtime);
-
 					/* average transfers per second. */
-		(void)printf(" %5.0f",
+		(void)printf(" %*.0f", c1,
 		    (cur.rxfer[dn] + cur.wxfer[dn]) / dtime);
 
+					/* average kbytes per second. */
+		(void)printf(" %*.0f", c2,
+		    (cur.rbytes[dn] + cur.wbytes[dn]) / 1024.0 / dtime);
+
 					/* average time busy in drive activity */
 		atime = (double)cur.time[dn].tv_sec +
 		    ((double)cur.time[dn].tv_usec / (double)1000000);
-		(void)printf(" %4.2f ", atime / dtime);
+		(void)printf(" %*.2f ", c3, atime / dtime);
 	}
 }
 


Home | Main Index | Thread Index | Old Index