Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Apr 2004 14:27:30 -0500
From:      Dan Nelson <dnelson@allantgroup.com>
To:        Aditya <aditya@grot.org>
Cc:        questions@freebsd.org
Subject:   Re: read/write disk bandwidth monitoring?
Message-ID:  <20040414192730.GC28745@dan.emsphone.com>
In-Reply-To: <20040414190225.GF34327@mighty.grot.org>
References:  <20040414190225.GF34327@mighty.grot.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--PEIAKu/WMn1b1Hv9
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

In the last episode (Apr 14), Aditya said:
> iostat can provide an aggregate number for transactions per second and Bytes
> per transaction for a given device, but if it is a block device, is there a
> counter accessible from iostat or elsewhere that I can see how much is read
> transactions versus write transactions?
> 
> > iostat -K -d -I 1
>              ad0              ad2              da0            pass0
>   KB/t xfrs   MB   KB/t xfrs   MB   KB/t xfrs   MB   KB/t xfrs   MB
>   0.00   0  0.00   0.00   0  0.00   0.00   0  0.00   0.00   0  0.00
>   7.50   8  0.06   0.00   0  0.00   0.00   0  0.00   0.00   0  0.00
>   0.00   0  0.00   0.00   0  0.00   0.00   0  0.00   0.00   0  0.00
>   0.00   0  0.00   0.00   0  0.00   0.00   0  0.00   0.00   0  0.00
> ^C
> 
> tells me transactions per device, but not divided into reads versus writes...

This is definitely possible, but iostat doesn't currently print it.  I
have patches that add a Solaris-style -x flag to iostat, which gives you
output like:

$ iostat -x 1
                                  extended device statistics
device     r/s   w/s    kr/s    kw/s wait actv svc_t  %w  %b
da0       29.7  24.8   466.3   249.5    0    1  33.5   0  46
cd0        0.0   0.0     0.0     0.0    0    0   0.0   0   0
cd1        0.0   0.0     0.0     0.0    0    0   0.0   0   0


On -current, you can also use the "gstat" command (run it as root),
which can give you read and write stats down to the partition level.


-- 
	Dan Nelson
	dnelson@allantgroup.com

--PEIAKu/WMn1b1Hv9
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="iostat.diff"

Index: iostat.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/iostat/iostat.c,v
retrieving revision 1.28
diff -u -r1.28 iostat.c
--- iostat.c	15 Mar 2003 21:59:06 -0000	1.28
+++ iostat.c	17 Apr 2003 02:49:27 -0000
@@ -136,7 +136,7 @@
 struct device_selection *dev_select;
 int maxshowdevs;
 volatile sig_atomic_t headercount;
-int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0;
+int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0, xflag = 0;
 
 /* local function declarations */
 static void usage(void);
@@ -156,7 +156,7 @@
 	 * This isn't mentioned in the man page, or the usage statement,
 	 * but it is supported.
 	 */
-	fprintf(stderr, "usage: iostat [-CdhIKoT?] [-c count] [-M core]"
+	fprintf(stderr, "usage: iostat [-CdhIKoTx?] [-c count] [-M core]"
 		" [-n devs] [-N system]\n"
 		"\t      [-t type,if,pass] [-w wait] [drives]\n");
 }
@@ -184,7 +184,7 @@
 	matches = NULL;
 	maxshowdevs = 3;
 
-	while ((c = getopt(argc, argv, "c:CdhIKM:n:N:ot:Tw:?")) != -1) {
+	while ((c = getopt(argc, argv, "c:CdhIKl:M:n:N:ot:Tw:x?")) != -1) {
 		switch(c) {
 			case 'c':
 				cflag++;
@@ -211,6 +211,7 @@
 				memf = optarg;
 				break;
 			case 'n':
+			case 'l':
 				nflag++;
 				maxshowdevs = atoi(optarg);
 				if (maxshowdevs < 0)
@@ -238,6 +239,9 @@
 				if (waittime < 1)
 					errx(1, "wait time is < 1");
 				break;
+			case 'x':
+				xflag++;
+				break;
 			default:
 				usage();
 				exit(1);
@@ -270,7 +274,7 @@
 	 * Make sure Tflag and/or Cflag are set if dflag == 0.  If dflag is
 	 * greater than 0, they may be 0 or non-zero.
 	 */
-	if (dflag == 0) {
+	if (dflag == 0 && xflag == 0) {
 		Cflag = 1;
 		Tflag = 1;
 	}
@@ -547,16 +551,18 @@
 			last.cp_time[i] = tmp;
 		}
 
-		if (Tflag > 0)
+		if (Tflag > 0 && !xflag)
 			printf("%4.0Lf%5.0Lf", cur.tk_nin / etime, 
 				cur.tk_nout/etime);
 
 		devstats(hflag, etime, havelast);
 
-		if (Cflag > 0)
+		if (Cflag > 0 && !xflag)
 			cpustats();
 
-		printf("\n");
+		if (!xflag)
+			printf("\n");
+		
 		fflush(stdout);
 
 		if (count >= 0 && --count <= 0)
@@ -584,7 +590,9 @@
 {
 	register int i;
 	int printed;
-
+	
+	if (xflag)
+		return;
 	if (Tflag > 0)
 		(void)printf("      tty");
 	for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){
@@ -639,11 +647,29 @@
 devstats(int perf_select, long double etime, int havelast)
 {
 	register int dn;
-	long double transfers_per_second;
-	long double kb_per_transfer, mb_per_second;
+	long double transfers_per_second,transfers_per_second_read,transfers_per_second_write;
+	long double kb_per_transfer, mb_per_second, mb_per_second_read, mb_per_second_write;
 	u_int64_t total_bytes, total_transfers, total_blocks;
+	long double busy_pct;
+	u_int64_t queue_len;
 	long double total_mb;
 	long double blocks_per_second, ms_per_transaction;
+	int firstline = 1;
+
+	if (xflag) {
+		printf ("                                  extended device statistics  ");
+		if (Tflag)
+			printf ("     tty ");
+		if (Cflag)
+			printf ("           cpu ");
+		printf ("\n");
+		printf ("device     r/s   w/s    kr/s    kw/s wait actv svc_t  %%w  %%b  ");
+		if (Tflag)
+			printf ("tin tout ");
+		if (Cflag)
+			printf ("us ni sy in id ");
+		printf ("\n");
+	}
 	
 	for (dn = 0; dn < num_devices; dn++) {
 		int di;
@@ -661,9 +687,15 @@
 		    DSM_TOTAL_BLOCKS, &total_blocks,
 		    DSM_KB_PER_TRANSFER, &kb_per_transfer,
 		    DSM_TRANSFERS_PER_SECOND, &transfers_per_second,
+		    DSM_TRANSFERS_PER_SECOND_READ, &transfers_per_second_read,
+		    DSM_TRANSFERS_PER_SECOND_WRITE, &transfers_per_second_write,
 		    DSM_MB_PER_SECOND, &mb_per_second, 
+		    DSM_MB_PER_SECOND_READ, &mb_per_second_read, 
+		    DSM_MB_PER_SECOND_WRITE, &mb_per_second_write, 
 		    DSM_BLOCKS_PER_SECOND, &blocks_per_second,
 		    DSM_MS_PER_TRANSACTION, &ms_per_transaction,
+			DSM_BUSY_PCT, &busy_pct,
+			DSM_QUEUE_LENGTH, &queue_len,
 		    DSM_NONE) != 0)
 			errx(1, "%s", devstat_errbuf);
 
@@ -674,13 +706,34 @@
 				continue;
 		}
 
-		if (Kflag) {
+		if (Kflag || xflag) {
 			int block_size = cur.dinfo->devices[di].block_size;
 			total_blocks = total_blocks * (block_size ?
 						       block_size : 512) / 1024;
 		}
 
-		if (oflag > 0) {
+		if (xflag > 0) {
+			char *devname;
+			asprintf(&devname,"%s%d",
+				cur.dinfo->devices[di].device_name,
+			    cur.dinfo->devices[di].unit_number);
+			printf ("%-8.8s %5.1Lf %5.1Lf %7.1Lf %7.1Lf %4qu %4qu %5.1Lf %3.0Lf %3.0Lf ", 
+				devname,
+				transfers_per_second_read, transfers_per_second_write,
+				mb_per_second_read*1024, mb_per_second_write*1024,
+				(u_int64_t)0,queue_len,ms_per_transaction,(long double)0.0,busy_pct
+				);
+			free(devname);
+			if (firstline) {
+				firstline = 0;
+				if (Tflag > 0)
+					printf("%4.0Lf%5.0Lf ", cur.tk_nin / etime, 
+						cur.tk_nout/etime);
+				if (Cflag > 0)
+					cpustats();
+			}
+			printf ("\n");
+		} else if (oflag > 0) {
 			int msdig = (ms_per_transaction < 100.0) ? 1 : 0;
 
 			if (Iflag == 0)
@@ -727,6 +780,7 @@
 	for (state = 0; state < CPUSTATES; ++state)
 		printf(" %2.0f",
 		       rint(100. * cur.cp_time[state] / (time ? time : 1)));
+	printf(" ");
 }
 
 static int

--PEIAKu/WMn1b1Hv9--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040414192730.GC28745>