Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Jun 2004 22:30:18 GMT
From:      Dan Nelson <dnelson@allantgroup.com>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: misc/67687: read/write disk bandwidth monitoring?
Message-ID:  <200406072230.i57MUIxI016388@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR misc/67687; it has been noted by GNATS.

From: Dan Nelson <dnelson@allantgroup.com>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: misc/67687: read/write disk bandwidth monitoring?
Date: Wed, 14 Apr 2004 14:27:30 -0500

 --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?200406072230.i57MUIxI016388>