Add "diskinfo -i", a simple aio-based IOPS benchmark.
MFC after: 1 month
This commit is contained in:
parent
f38db92af3
commit
54f79d39a9
usr.sbin/diskinfo
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user