svn commit: r306160 - head/usr.sbin/diskinfo

Edward Tomasz Napierala trasz at FreeBSD.org
Thu Sep 22 07:33:44 UTC 2016


Author: trasz
Date: Thu Sep 22 07:33:43 2016
New Revision: 306160
URL: https://svnweb.freebsd.org/changeset/base/306160

Log:
  Add "diskinfo -i", a simple aio-based IOPS benchmark.
  
  MFC after:	1 month

Modified:
  head/usr.sbin/diskinfo/diskinfo.8
  head/usr.sbin/diskinfo/diskinfo.c

Modified: head/usr.sbin/diskinfo/diskinfo.8
==============================================================================
--- head/usr.sbin/diskinfo/diskinfo.8	Thu Sep 22 06:24:40 2016	(r306159)
+++ head/usr.sbin/diskinfo/diskinfo.8	Thu Sep 22 07:33:43 2016	(r306160)
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 9, 2004
+.Dd September 22, 2016
 .Dt DISKINFO 8
 .Os
 .Sh NAME
@@ -36,7 +36,7 @@
 .Nd get information about disk device
 .Sh SYNOPSIS
 .Nm
-.Op Fl ctv
+.Op Fl citv
 .Ar disk ...
 .Sh DESCRIPTION
 The
@@ -59,6 +59,10 @@ The
 option triggers a simple measurement of the I/O read command overhead.
 .Pp
 The
+.Fl i
+option triggers a simple IOPS benchmark.
+.Pp
+The
 .Fl t
 option triggers a simple and rather naive benchmark of the disks seek
 and transfer performance.

Modified: head/usr.sbin/diskinfo/diskinfo.c
==============================================================================
--- head/usr.sbin/diskinfo/diskinfo.c	Thu Sep 22 06:24:40 2016	(r306159)
+++ head/usr.sbin/diskinfo/diskinfo.c	Thu Sep 22 07:33:43 2016	(r306160)
@@ -40,22 +40,26 @@
 #include <libutil.h>
 #include <paths.h>
 #include <err.h>
+#include <sys/aio.h>
 #include <sys/disk.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#define	NAIO	128
+
 static void
 usage(void)
 {
-	fprintf(stderr, "usage: diskinfo [-ctv] disk ...\n");
+	fprintf(stderr, "usage: diskinfo [-citv] disk ...\n");
 	exit (1);
 }
 
-static int opt_c, opt_t, opt_v;
+static int opt_c, opt_i, opt_t, opt_v;
 
 static void speeddisk(int fd, off_t mediasize, u_int sectorsize);
 static void commandtime(int fd, off_t mediasize, u_int sectorsize);
+static void iopsbench(int fd, off_t mediasize, u_int sectorsize);
 static int zonecheck(int fd, uint32_t *zone_mode, char *zone_str,
 		     size_t zone_str_len);
 
@@ -70,12 +74,16 @@ main(int argc, char **argv)
 	u_int	sectorsize, fwsectors, fwheads, zoned = 0;
 	uint32_t zone_mode;
 
-	while ((ch = getopt(argc, argv, "ctv")) != -1) {
+	while ((ch = getopt(argc, argv, "citv")) != -1) {
 		switch (ch) {
 		case 'c':
 			opt_c = 1;
 			opt_v = 1;
 			break;
+		case 'i':
+			opt_i = 1;
+			opt_v = 1;
+			break;
 		case 't':
 			opt_t = 1;
 			opt_v = 1;
@@ -188,6 +196,8 @@ main(int argc, char **argv)
 			commandtime(fd, mediasize, sectorsize);
 		if (opt_t)
 			speeddisk(fd, mediasize, sectorsize);
+		if (opt_i)
+			iopsbench(fd, mediasize, sectorsize);
 out:
 		close(fd);
 	}
@@ -270,6 +280,16 @@ TR(double count)
 }
 
 static void
+TI(double count)
+{
+	double dt;
+
+	dt = delta_t();
+	printf("%8.0f ops in  %10.6f sec = %8.0f IOPS\n",
+		count, dt, count / dt);
+}
+
+static void
 speeddisk(int fd, off_t mediasize, u_int sectorsize)
 {
 	int bulk, i;
@@ -418,6 +438,91 @@ commandtime(int fd, off_t mediasize, u_i
 	return;
 }
 
+static void
+iops(int fd, off_t mediasize, u_int sectorsize)
+{
+	struct aiocb aios[NAIO], *aiop;
+	ssize_t ret;
+	off_t sectorcount;
+	int error, i, queued, completed;
+
+	sectorcount = mediasize / sectorsize;
+
+	for (i = 0; i < NAIO; i++) {
+		aiop = &(aios[i]);
+		bzero(aiop, sizeof(*aiop));
+		aiop->aio_buf = malloc(sectorsize);
+		if (aiop->aio_buf == NULL)
+			err(1, "malloc");
+	}
+
+	T0();
+	for (i = 0; i < NAIO; i++) {
+		aiop = &(aios[i]);
+
+		aiop->aio_fildes = fd;
+		aiop->aio_offset = (random() % (sectorcount)) * sectorsize;
+		aiop->aio_nbytes = sectorsize;
+
+		error = aio_read(aiop);
+		if (error != 0)
+			err(1, "aio_read");
+	}
+
+	queued = i;
+	completed = 0;
+
+	for (;;) {
+		ret = aio_waitcomplete(&aiop, NULL);
+		if (ret < 0)
+			err(1, "aio_waitcomplete");
+		if (ret != (ssize_t)sectorsize)
+			errx(1, "short read");
+
+		completed++;
+
+		if (delta_t() < 3.0) {
+			aiop->aio_fildes = fd;
+			aiop->aio_offset = (random() % (sectorcount)) * sectorsize;
+			aiop->aio_nbytes = sectorsize;
+
+			error = aio_read(aiop);
+			if (error != 0)
+				err(1, "aio_read");
+
+			queued++;
+		} else if (completed == queued) {
+			break;
+		}
+	}
+
+	TI(completed);
+
+	return;
+}
+
+static void
+iopsbench(int fd, off_t mediasize, u_int sectorsize)
+{
+	printf("Asynchronous random reads:\n");
+
+	printf("\tsectorsize:  ");
+	iops(fd, mediasize, sectorsize);
+
+	if (sectorsize != 4096) {
+		printf("\t4 kbytes:    ");
+		iops(fd, mediasize, 4096);
+	}
+
+	printf("\t32 kbytes:   ");
+	iops(fd, mediasize, 32 * 1024);
+
+	printf("\t128 kbytes:  ");
+	iops(fd, mediasize, 128 * 1024);
+
+	printf("\n");
+}
+
 static int
 zonecheck(int fd, uint32_t *zone_mode, char *zone_str, size_t zone_str_len)
 {


More information about the svn-src-all mailing list