From owner-svn-src-user@FreeBSD.ORG Tue Aug 10 14:44:21 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1ECF31065686; Tue, 10 Aug 2010 14:44:21 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0DF4E8FC2D; Tue, 10 Aug 2010 14:44:21 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o7AEiKmr049088; Tue, 10 Aug 2010 14:44:20 GMT (envelope-from des@svn.freebsd.org) Received: (from des@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o7AEiKkD049085; Tue, 10 Aug 2010 14:44:20 GMT (envelope-from des@svn.freebsd.org) Message-Id: <201008101444.o7AEiKkD049085@svn.freebsd.org> From: Dag-Erling Smorgrav Date: Tue, 10 Aug 2010 14:44:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r211147 - user/des/phybs X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Aug 2010 14:44:21 -0000 Author: des Date: Tue Aug 10 14:44:20 2010 New Revision: 211147 URL: http://svn.freebsd.org/changeset/base/211147 Log: This is a small program that runs a series of performance tests designed to reveal the physical block size of a disk. It performs a series of staggered reads and / or writes of different lengths at different alignments. The idea is that a disk that has a large physical blocksize but simulates a smaller one will perform poorly, due to read-modify-write, except when both the I/O size and the offset are multiples of the physical block size. The program supports read-only, write-only and read-write tests. The default is write-only. A read-write test is probably not very useful, because it primes the cache in cases where the disk would actually perform an extra read. A read-only test is useless except as a quick way to verify that the program works. Note that the program currently assumes a logical block size of 512 bytes and that the parameters (size range, interval and iterations) are hardcoded. Added: user/des/phybs/ user/des/phybs/Makefile (contents, props changed) user/des/phybs/phybs.c (contents, props changed) Added: user/des/phybs/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/des/phybs/Makefile Tue Aug 10 14:44:20 2010 (r211147) @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG = phybs +CSTD ?= c99 +WARNS ?= 6 +MAN = # none + +.include "../Makefile.inc" +.include Added: user/des/phybs/phybs.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/des/phybs/phybs.c Tue Aug 10 14:44:20 2010 (r211147) @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2010 Dag-Erling Coïdan Smørgrav + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +#include +#include +#include +#include +#include +#include + +#define MINSIZE 512 +#define MAXSIZE 8192 +#define STEP MAXSIZE +#define COUNT 65536 + +static int opt_r = 0; +static int opt_w = 1; + +static void +scan(int fd, size_t size, off_t offset, off_t step, unsigned int count) +{ + struct timeval t0, t1; + unsigned long usec; + ssize_t rlen, wlen; + char *buf; + + printf("%8u%8lu%8lu%8lu", count, (unsigned long)size, + (unsigned long)offset, (unsigned long)step); + fflush(stdout); + if ((buf = malloc(size)) == NULL) + err(1, "malloc()"); + memset(buf, 0, size); + if (gettimeofday(&t0, NULL) == -1) + err(1, "gettimeofday()"); + for (unsigned int i = 0; i < count; ++i, offset += step) { + if (opt_r) { + if (lseek(fd, offset, SEEK_SET) != offset) + err(1, "lseek(%lu)", (unsigned long)offset); + if ((rlen = read(fd, buf, size)) == -1) + err(1, "read(%lu)", (unsigned long)size); + if (rlen < (ssize_t)size) + errx(1, "short read: %ld < %lu", + (long)rlen, (unsigned long)size); + } + if (opt_w) { + if (lseek(fd, offset, SEEK_SET) != offset) + err(1, "lseek(%lu)", (unsigned long)offset); + if ((wlen = write(fd, buf, size)) == -1) + err(1, "write(%lu)", (unsigned long)size); + if (wlen < (ssize_t)size) + errx(1, "short write: %ld < %lu", + (long)wlen, (unsigned long)size); + } + } + if (gettimeofday(&t1, NULL) == -1) + err(1, "gettimeofday()"); + usec = t1.tv_sec * 1000000 + t1.tv_usec; + usec -= t0.tv_sec * 1000000 + t0.tv_usec; + printf("%12lu%8lu%8lu\n", usec / 1000, + count * 1000000 / usec, + count * size * 1000000 / 1024 / usec); + free(buf); +} + +static void +usage(void) +{ + + fprintf(stderr, "usage: phybs [-R | -r] [-W | -w] device\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *device; + int fd, opt; + + while ((opt = getopt(argc, argv, "RrWw")) != -1) + switch (opt) { + case 'R': + opt_r = 0; + break; + case 'r': + opt_r = 1; + break; + case 'W': + opt_w = 0; + break; + case 'w': + opt_w = 1; + break; + default: + usage(); + } + + argc -= optind; + argv += optind; + + if (argc != 1) + usage(); + + if (!opt_r && !opt_w) + opt_r = opt_w = 1; + + device = argv[0]; + if ((fd = open(device, opt_w ? O_RDWR : O_RDONLY)) == -1) + err(1, "open(%s)", device); + printf("%8s%8s%8s%8s%12s%8s%8s\n", + "count", "size", "offset", "step", + "msec", "tps", "kBps"); + for (size_t size = MINSIZE; size <= MAXSIZE; size *= 2) + for (off_t offset = 0; offset < (off_t)size; offset += 512) + scan(fd, size, offset, STEP, COUNT); + close(fd); + exit(0); +}