perftest.c revision 256152
1252267Sjimharris/*- 2252267Sjimharris * Copyright (C) 2012-2013 Intel Corporation 3252267Sjimharris * All rights reserved. 4252267Sjimharris * 5252267Sjimharris * Redistribution and use in source and binary forms, with or without 6252267Sjimharris * modification, are permitted provided that the following conditions 7252267Sjimharris * are met: 8252267Sjimharris * 1. Redistributions of source code must retain the above copyright 9252267Sjimharris * notice, this list of conditions and the following disclaimer. 10252267Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 11252267Sjimharris * notice, this list of conditions and the following disclaimer in the 12252267Sjimharris * documentation and/or other materials provided with the distribution. 13252267Sjimharris * 14252267Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15252267Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16252267Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17252267Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18252267Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19252267Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20252267Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21252267Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22252267Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23252267Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24252267Sjimharris * SUCH DAMAGE. 25252267Sjimharris */ 26252267Sjimharris 27252267Sjimharris#include <sys/cdefs.h> 28252267Sjimharris__FBSDID("$FreeBSD: head/sbin/nvmecontrol/perftest.c 256152 2013-10-08 15:47:22Z jimharris $"); 29252267Sjimharris 30252267Sjimharris#include <sys/param.h> 31252267Sjimharris#include <sys/ioccom.h> 32252267Sjimharris 33252267Sjimharris#include <ctype.h> 34253109Sjimharris#include <err.h> 35252267Sjimharris#include <fcntl.h> 36256152Sjimharris#include <inttypes.h> 37252267Sjimharris#include <stdbool.h> 38252267Sjimharris#include <stddef.h> 39252267Sjimharris#include <stdio.h> 40252267Sjimharris#include <stdlib.h> 41252267Sjimharris#include <string.h> 42252267Sjimharris#include <unistd.h> 43252267Sjimharris 44252267Sjimharris#include "nvmecontrol.h" 45252267Sjimharris 46252267Sjimharrisstatic void 47252267Sjimharrisprint_perftest(struct nvme_io_test *io_test, bool perthread) 48252267Sjimharris{ 49256152Sjimharris uint64_t io_completed = 0, iops, mbps; 50256152Sjimharris uint32_t i; 51252267Sjimharris 52252267Sjimharris for (i = 0; i < io_test->num_threads; i++) 53252267Sjimharris io_completed += io_test->io_completed[i]; 54252267Sjimharris 55252267Sjimharris iops = io_completed/io_test->time; 56252267Sjimharris mbps = iops * io_test->size / (1024*1024); 57252267Sjimharris 58256152Sjimharris printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7ju MB/s: %4ju\n", 59252267Sjimharris io_test->num_threads, io_test->size, 60252267Sjimharris io_test->opc == NVME_OPC_READ ? "READ" : "WRITE", 61256152Sjimharris io_test->time, (uintmax_t)iops, (uintmax_t)mbps); 62252267Sjimharris 63252267Sjimharris if (perthread) 64252267Sjimharris for (i = 0; i < io_test->num_threads; i++) 65256152Sjimharris printf("\t%3d: %8ju IO/s\n", i, 66256152Sjimharris (uintmax_t)io_test->io_completed[i]/io_test->time); 67252267Sjimharris 68252267Sjimharris exit(1); 69252267Sjimharris} 70252267Sjimharris 71252267Sjimharrisstatic void 72252267Sjimharrisperftest_usage(void) 73252267Sjimharris{ 74252267Sjimharris fprintf(stderr, "usage:\n"); 75252267Sjimharris fprintf(stderr, PERFTEST_USAGE); 76253109Sjimharris exit(1); 77252267Sjimharris} 78252267Sjimharris 79252267Sjimharrisvoid 80252267Sjimharrisperftest(int argc, char *argv[]) 81252267Sjimharris{ 82252267Sjimharris struct nvme_io_test io_test; 83252267Sjimharris int fd; 84252267Sjimharris char ch; 85252267Sjimharris char *p; 86252267Sjimharris u_long ioctl_cmd = NVME_IO_TEST; 87252267Sjimharris bool nflag, oflag, sflag, tflag; 88252267Sjimharris int perthread = 0; 89252267Sjimharris 90252267Sjimharris nflag = oflag = sflag = tflag = false; 91252267Sjimharris 92252267Sjimharris memset(&io_test, 0, sizeof(io_test)); 93252267Sjimharris 94252267Sjimharris while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) { 95252267Sjimharris switch (ch) { 96252267Sjimharris case 'f': 97252267Sjimharris if (!strcmp(optarg, "refthread")) 98252267Sjimharris io_test.flags |= NVME_TEST_FLAG_REFTHREAD; 99252267Sjimharris break; 100252267Sjimharris case 'i': 101252267Sjimharris if (!strcmp(optarg, "bio") || 102252267Sjimharris !strcmp(optarg, "wait")) 103252267Sjimharris ioctl_cmd = NVME_BIO_TEST; 104252267Sjimharris else if (!strcmp(optarg, "io") || 105252267Sjimharris !strcmp(optarg, "intr")) 106252267Sjimharris ioctl_cmd = NVME_IO_TEST; 107252267Sjimharris break; 108252267Sjimharris case 'n': 109252267Sjimharris nflag = true; 110252267Sjimharris io_test.num_threads = strtoul(optarg, &p, 0); 111252267Sjimharris if (p != NULL && *p != '\0') { 112252267Sjimharris fprintf(stderr, 113252267Sjimharris "\"%s\" not valid number of threads.\n", 114252267Sjimharris optarg); 115252267Sjimharris perftest_usage(); 116252267Sjimharris } else if (io_test.num_threads == 0 || 117252267Sjimharris io_test.num_threads > 128) { 118252267Sjimharris fprintf(stderr, 119252267Sjimharris "\"%s\" not valid number of threads.\n", 120252267Sjimharris optarg); 121252267Sjimharris perftest_usage(); 122252267Sjimharris } 123252267Sjimharris break; 124252267Sjimharris case 'o': 125252267Sjimharris oflag = true; 126252267Sjimharris if (!strcmp(optarg, "read") || !strcmp(optarg, "READ")) 127252267Sjimharris io_test.opc = NVME_OPC_READ; 128252267Sjimharris else if (!strcmp(optarg, "write") || 129252267Sjimharris !strcmp(optarg, "WRITE")) 130252267Sjimharris io_test.opc = NVME_OPC_WRITE; 131252267Sjimharris else { 132252267Sjimharris fprintf(stderr, "\"%s\" not valid opcode.\n", 133252267Sjimharris optarg); 134252267Sjimharris perftest_usage(); 135252267Sjimharris } 136252267Sjimharris break; 137252267Sjimharris case 'p': 138252267Sjimharris perthread = 1; 139252267Sjimharris break; 140252267Sjimharris case 's': 141252267Sjimharris sflag = true; 142252267Sjimharris io_test.size = strtoul(optarg, &p, 0); 143252267Sjimharris if (p == NULL || *p == '\0' || toupper(*p) == 'B') { 144252267Sjimharris // do nothing 145252267Sjimharris } else if (toupper(*p) == 'K') { 146252267Sjimharris io_test.size *= 1024; 147252267Sjimharris } else if (toupper(*p) == 'M') { 148252267Sjimharris io_test.size *= 1024 * 1024; 149252267Sjimharris } else { 150252267Sjimharris fprintf(stderr, "\"%s\" not valid size.\n", 151252267Sjimharris optarg); 152252267Sjimharris perftest_usage(); 153252267Sjimharris } 154252267Sjimharris break; 155252267Sjimharris case 't': 156252267Sjimharris tflag = true; 157252267Sjimharris io_test.time = strtoul(optarg, &p, 0); 158252267Sjimharris if (p != NULL && *p != '\0') { 159252267Sjimharris fprintf(stderr, 160252267Sjimharris "\"%s\" not valid time duration.\n", 161252267Sjimharris optarg); 162252267Sjimharris perftest_usage(); 163252267Sjimharris } 164252267Sjimharris break; 165252267Sjimharris } 166252267Sjimharris } 167252267Sjimharris 168252267Sjimharris if (!nflag || !oflag || !sflag || !tflag || optind >= argc) 169252267Sjimharris perftest_usage(); 170252267Sjimharris 171252267Sjimharris open_dev(argv[optind], &fd, 1, 1); 172253109Sjimharris if (ioctl(fd, ioctl_cmd, &io_test) < 0) 173253109Sjimharris err(1, "ioctl NVME_IO_TEST failed"); 174252267Sjimharris 175252267Sjimharris close(fd); 176252267Sjimharris print_perftest(&io_test, perthread); 177253109Sjimharris exit(0); 178252267Sjimharris} 179