read/write disk bandwidth monitoring?
Dan Nelson
dnelson at allantgroup.com
Wed Apr 14 12:27:31 PDT 2004
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 at allantgroup.com
-------------- next part --------------
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
More information about the freebsd-questions
mailing list