commit 64e05e2202b91366dbbcdc07399cd192fdc9e6bf Author: Mikolaj Golub Date: Tue Sep 18 12:35:17 2012 +0300 New devstat metrics for devstat_compute_statistics(): DSM_TOTAL_DURATION DSM_TOTAL_DURATION_READ DSM_TOTAL_DURATION_WRITE DSM_TOTAL_DURATION_FREE DSM_TOTAL_DURATION_OTHER DSM_TOTAL_BUSY_TIME diff --git a/lib/libdevstat/devstat.3 b/lib/libdevstat/devstat.3 index 8d0ce4d..a784e47 100644 --- a/lib/libdevstat/devstat.3 +++ b/lib/libdevstat/devstat.3 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 18, 2003 +.Dd September 18, 2012 .Dt DEVSTAT 3 .Os .Sh NAME @@ -526,6 +526,35 @@ the acquisition of .Fa previous and .Fa current . +.It Dv DSM_TOTAL_DURATION +type: +.Vt "long double *" +.Pp +The total duration of transactions, in seconds, between the acquisition of +.Fa previous +and +.Fa current . +.It Dv DSM_TOTAL_DURATION_OTHER +.It Dv DSM_TOTAL_DURATION_READ +.It Dv DSM_TOTAL_DURATION_WRITE +.It Dv DSM_TOTAL_DURATION_FREE +type: +.Vt "long double *" +.Pp +The total duration of transactions of the specified type between +the acquisition of +.Fa previous +and +.Fa current . +.It Dv DSM_TOTAL_BUSY_TIME +type: +.Vt "long double *" +.Pp +Total time the device had one or more transactions outstanding +between the acquisition of +.Fa previous +and +.Fa current . .It Dv DSM_TOTAL_BLOCKS type: .Vt "uint64_t *" diff --git a/lib/libdevstat/devstat.c b/lib/libdevstat/devstat.c index ff0767a..0f313fb 100644 --- a/lib/libdevstat/devstat.c +++ b/lib/libdevstat/devstat.c @@ -133,6 +133,12 @@ struct devstat_args { { DSM_MS_PER_TRANSACTION_FREE, DEVSTAT_ARG_LD }, { DSM_BUSY_PCT, DEVSTAT_ARG_LD }, { DSM_QUEUE_LENGTH, DEVSTAT_ARG_UINT64 }, + { DSM_TOTAL_DURATION, DEVSTAT_ARG_LD }, + { DSM_TOTAL_DURATION_READ, DEVSTAT_ARG_LD }, + { DSM_TOTAL_DURATION_WRITE, DEVSTAT_ARG_LD }, + { DSM_TOTAL_DURATION_FREE, DEVSTAT_ARG_LD }, + { DSM_TOTAL_DURATION_OTHER, DEVSTAT_ARG_LD }, + { DSM_TOTAL_BUSY_TIME, DEVSTAT_ARG_LD }, }; static const char *namelist[] = { @@ -1217,11 +1223,13 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, u_int64_t totaltransfers, totaltransfersread, totaltransferswrite; u_int64_t totaltransfersother, totalblocks, totalblocksread; u_int64_t totalblockswrite, totaltransfersfree, totalblocksfree; + long double totalduration, totaldurationread, totaldurationwrite; + long double totaldurationfree, totaldurationother; va_list ap; devstat_metric metric; u_int64_t *destu64; long double *destld; - int retval, i; + int retval; retval = 0; @@ -1263,6 +1271,13 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, totalblocksfree /= 512; } + totaldurationread = DELTA_T(duration[DEVSTAT_READ]); + totaldurationwrite = DELTA_T(duration[DEVSTAT_WRITE]); + totaldurationfree = DELTA_T(duration[DEVSTAT_FREE]); + totaldurationother = DELTA_T(duration[DEVSTAT_NO_DATA]); + totalduration = totaldurationread + totaldurationwrite + + totaldurationfree + totaldurationother; + va_start(ap, etime); while ((metric = (devstat_metric)va_arg(ap, devstat_metric)) != 0) { @@ -1484,9 +1499,7 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, */ case DSM_MS_PER_TRANSACTION: if (totaltransfers > 0) { - *destld = 0; - for (i = 0; i < DEVSTAT_N_TRANS_FLAGS; i++) - *destld += DELTA_T(duration[i]); + *destld = totalduration; *destld /= totaltransfers; *destld *= 1000; } else @@ -1499,7 +1512,7 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, */ case DSM_MS_PER_TRANSACTION_READ: if (totaltransfersread > 0) { - *destld = DELTA_T(duration[DEVSTAT_READ]); + *destld = totaldurationread; *destld /= totaltransfersread; *destld *= 1000; } else @@ -1507,7 +1520,7 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, break; case DSM_MS_PER_TRANSACTION_WRITE: if (totaltransferswrite > 0) { - *destld = DELTA_T(duration[DEVSTAT_WRITE]); + *destld = totaldurationwrite; *destld /= totaltransferswrite; *destld *= 1000; } else @@ -1515,7 +1528,7 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, break; case DSM_MS_PER_TRANSACTION_FREE: if (totaltransfersfree > 0) { - *destld = DELTA_T(duration[DEVSTAT_FREE]); + *destld = totaldurationfree; *destld /= totaltransfersfree; *destld *= 1000; } else @@ -1523,7 +1536,7 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, break; case DSM_MS_PER_TRANSACTION_OTHER: if (totaltransfersother > 0) { - *destld = DELTA_T(duration[DEVSTAT_NO_DATA]); + *destld = totaldurationother; *destld /= totaltransfersother; *destld *= 1000; } else @@ -1541,6 +1554,24 @@ devstat_compute_statistics(struct devstat *current, struct devstat *previous, case DSM_QUEUE_LENGTH: *destu64 = current->start_count - current->end_count; break; + case DSM_TOTAL_DURATION: + *destld = totalduration; + break; + case DSM_TOTAL_DURATION_READ: + *destld = totaldurationread; + break; + case DSM_TOTAL_DURATION_WRITE: + *destld = totaldurationwrite; + break; + case DSM_TOTAL_DURATION_FREE: + *destld = totaldurationfree; + break; + case DSM_TOTAL_DURATION_OTHER: + *destld = totaldurationother; + break; + case DSM_TOTAL_BUSY_TIME: + *destld = DELTA_T(busy_time); + break; /* * XXX: comment out the default block to see if any case's are missing. */ diff --git a/lib/libdevstat/devstat.h b/lib/libdevstat/devstat.h index 7717cb1..9471f93 100644 --- a/lib/libdevstat/devstat.h +++ b/lib/libdevstat/devstat.h @@ -97,6 +97,12 @@ typedef enum { DSM_MS_PER_TRANSACTION_FREE, DSM_BUSY_PCT, DSM_QUEUE_LENGTH, + DSM_TOTAL_DURATION, + DSM_TOTAL_DURATION_READ, + DSM_TOTAL_DURATION_WRITE, + DSM_TOTAL_DURATION_FREE, + DSM_TOTAL_DURATION_OTHER, + DSM_TOTAL_BUSY_TIME, DSM_MAX } devstat_metric; commit dbf60592f7b0b68c41a1b0ff84a1effd09cf52d3 Author: Mikolaj Golub Date: Tue Sep 18 12:43:30 2012 +0300 Change `iostat -Ix` to display total duration of transactions instead of average duration, and total busy time instead of %. This looks more useful when one runs `iostat -Ix` periodically to collect statistics: e.g. now it is possible to calculate busy % between two runs subtracting total busy times and dividing per time period. Average duration and % busy are still available via `iostat -x`. diff --git a/usr.sbin/iostat/iostat.8 b/usr.sbin/iostat/iostat.8 index d8957ef..33df19e 100644 --- a/usr.sbin/iostat/iostat.8 +++ b/usr.sbin/iostat/iostat.8 @@ -56,7 +56,7 @@ .\" .\" @(#)iostat.8 8.1 (Berkeley) 6/6/93 .\" -.Dd November 24, 2010 +.Dd September 18, 2012 .Dt IOSTAT 8 .Os .Sh NAME @@ -366,6 +366,31 @@ average duration of transactions, in milliseconds % of time the device had one or more outstanding transactions .El .Pp +The extended +.Nm +device display, with the +.Fl x +and +.Fl I +flags specified, shows the following statistics: +.Pp +.Bl -tag -width indent -compact +.It r/i +read operations per time period +.It w/i +write operations per time period +.It kr/i +kilobytes read per time period +.It kw/i +kilobytes write per time period +.It qlen +transactions queue length +.It tdur +total duration of transactions, in seconds +.It sb +total time the device had one or more outstanding transactions, in seconds +.El +.Pp The old-style .Nm display (using diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c index 1c32f94..043d457 100644 --- a/usr.sbin/iostat/iostat.c +++ b/usr.sbin/iostat/iostat.c @@ -731,10 +731,10 @@ devstats(int perf_select, long double etime, int havelast) u_int64_t total_bytes, total_transfers, total_blocks; u_int64_t total_bytes_read, total_transfers_read; u_int64_t total_bytes_write, total_transfers_write; - long double busy_pct; + long double busy_pct, busy_time; u_int64_t queue_len; long double total_mb; - long double blocks_per_second, ms_per_transaction; + long double blocks_per_second, ms_per_transaction, total_duration; int firstline = 1; char *devname; @@ -745,14 +745,13 @@ devstats(int perf_select, long double etime, int havelast) if (Cflag > 0) printf(" cpu "); printf("\n"); - if (Iflag == 0) - printf( - "device r/s w/s kr/s kw/s qlen svc_t %%b " - ); - else - printf( - "device r/i w/i kr/i kw/i qlen svc_t %%b " - ); + if (Iflag == 0) { + printf("device r/s w/s kr/s kw/s qlen " + "svc_t %%b "); + } else { + printf("device r/i w/i kr/i" + " kw/i qlen tdur sb "); + } if (Tflag > 0) printf("tin tout "); if (Cflag > 0) @@ -789,6 +788,8 @@ devstats(int perf_select, long double etime, int havelast) DSM_MS_PER_TRANSACTION, &ms_per_transaction, DSM_BUSY_PCT, &busy_pct, DSM_QUEUE_LENGTH, &queue_len, + DSM_TOTAL_DURATION, &total_duration, + DSM_TOTAL_BUSY_TIME, &busy_time, DSM_NONE) != 0) errx(1, "%s", devstat_errbuf); @@ -827,7 +828,9 @@ devstats(int perf_select, long double etime, int havelast) queue_len, ms_per_transaction, busy_pct); else - printf("%-8.8s %5.1Lf %5.1Lf %7.1Lf %7.1Lf %4" PRIu64 " %5.1Lf %3.0Lf ", + printf("%-8.8s %11.1Lf %11.1Lf " + "%12.1Lf %12.1Lf %4" PRIu64 + " %10.1Lf %9.1Lf ", devname, (long double)total_transfers_read, (long double)total_transfers_write, @@ -836,7 +839,7 @@ devstats(int perf_select, long double etime, int havelast) (long double) total_bytes_write / 1024, queue_len, - ms_per_transaction, busy_pct); + total_duration, busy_time); if (firstline) { /* * If this is the first device