Add "diskinfo -i", a simple aio-based IOPS benchmark.

MFC after:	1 month
This commit is contained in:
Edward Tomasz Napierala 2016-09-22 07:33:43 +00:00
parent 5c6b397ff1
commit b76ce4527b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=306160
2 changed files with 114 additions and 5 deletions

View File

@ -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.

View File

@ -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);
}
@ -269,6 +279,16 @@ TR(double count)
count, dt, count / dt);
}
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)
{
@ -418,6 +438,91 @@ commandtime(int fd, off_t mediasize, u_int sectorsize)
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)
{