norcott@databs.enet.dec.com (Bill Norcott) (05/25/91)
Submitted-by: Bill Norcott <norcott@databs.enet.dec.com> Posting-number: Volume 20, Issue 19 Archive-name: iozone/part01 Supersedes: iozone: Volume 17, Issue 65 IOzone is an I/O benchmark which I have written. It is a performance test of sequential file I/O. IOzone calculates the speed at which your system reads and writes files, and prints the rate in bytes per second. This is a portable benchmark, and has been tested on VAX/VMS, MS-DOS, AIX, SCO UNIX, SUNOS, ULTRIX, etc. I would appreciate feedback on any changes needed to make it compile on Hewlett Packard, Apple, Interactive Unix, etc -- systems not already on my list. Attached is IOzone V1.08. This version includes auto test mode which performs a series of tests on file sizes from 1-16 MB and record lengths from 512 to 8192 bytes. It is invoked by the typing: iozone auto from the the shell. This version also fixes auto mode when compiled with Borland Turbo C on MS-DOS, and lets you compile IOzone on SUNOS without having to use -Dnolimits (the source code now compiles on SUNOS with the simple cc -o iozone iozone.c). Bill Norcott ------------------------ CUT HERE ------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: iozone.c # Wrapped by kent@sparky on Fri May 24 15:40:33 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive."' if test -f 'iozone.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'iozone.c'\" else echo shar: Extracting \"'iozone.c'\" \(14433 characters\) sed "s/^X//" >'iozone.c' <<'END_OF_FILE' X/* X* "IO Zone" Benchmark Program X* X* Author: Bill Norcott (Bill.Norcott@nuo.mts.dec.com) X* 4 Dunlap Drive X* Nashua, NH 03060 X* X* "Copyright 1991, William D. Norcott X* License to freely use and distribute this software is hereby granted X* by the author, subject to the condition that this copyright notice X* remains intact. The author retains the exclusive right to publish X* derivative works based on this work, including, but not limited, X* to revised versions of this work" X* X* "This test writes a 4 MEGABYTE sequential file in 512 byte chunks, then X* rewinds it and reads it back. [The size of the file should be X* big enough to factor out the effect of any disk cache.] X* X* The file is written (filling any cache buffers), and then read. If the X* cache is >= 4 MB, then most if not all the reads will be satisfied from X* the cache. However, if it is less than or equal to 2 MB, then NONE of X* the reads will be satisfied from the cache. This is becase after the X* file is written, a 2 MB cache will contain the upper 2 MB of the test X* file, but we will start reading from the beginning of the file (data X* which is no longer in the cache) X* X* In order for this to be a fair test, the length of the test file must X* be AT LEAST 2X the amount of disk cache memory for your system. If X* not, you are really testing the speed at which your CPU can read blocks X* out of the cache (not a fair test) X* X* IOZONE does NOT test the raw I/O speed of your disk or system. It X* tests the speed of sequential I/O to actual files. Therefore, this X* measurement factors in the efficiency of you machines file system, X* operating system, C compiler, and C runtime library. It produces a X* measurement which is the number of bytes per second that your system X* can read or write to a file. X* X* For V1.06, IOZONE adds the "auto test" feature. This is activated X* by the command: 'iozone auto' . The auto test runs IOZONE repeatedly X* using record sizes from 512 to 8192 bytes, and file sizes from 1 to 16 X* megabytes. It creates a table of results. X* X* For V1.06, IOZONE lets you specify the number of file system sizes and X* record lengths to test when using auto mode. Define the constants X* MEGABYTES_ITER_LIMIT and RECLEN_ITER_LIMIT as seen below X* X* This program has been ported and tested on the following computer X* operating systems: X* X* AIX Version 3 release 1 (compile: cc -Dunix -o iozone iozone.c) X* MS-DOS 3.3 (Turbo C, Turbo C++, Microsoft C) X* OSF/1 X* SCO Unix System V release 3.2 version 2 X* SUNOS 4.0.3, SUNOS 4.1.1 X* Ultrix V4.1 X* VAX/VMS V5.4 ** X* XENIX 3.2 X* X* ** for VMS, define iozone as a foreign command via this DCL command: X* X* $IOZONE :== $SYS$DISK:[]IOZONE.EXE X* X* this lets you pass the command line arguments to IOZONE X* X* Acknowledgements to the following persons for their feedback on IOzone: X* X* Andy Puchrik, Michael D. Lawler, Krishna E. Bera, Sam Drake, John H. Hartman, X* Ted Lyszczarz, Bill Metzenthen X* X* --- MODIFICATION HISTORY: X* X* 3/7/91 William D. Norcott (Bill.Norcott@nuo.mts.dec.com) X* created X* X* 3/22/91 Bill Norcott tested on OSF/1 ... it works X* X* 3/24/91 Bill Norcott V1.02 -- use calloc in TURBOC to X* fix bug with their malloc X* X* 3/25/91 Bill Norcott V1.03 -- add ifdef for XENIX X* X* 3/27/91 Bill Norcott V1.04 -- Includes for SCO UNIX X* X* 4/26/91 Bill Norcott V1.05 -- support AIX and SUNos, check X* length of read() and write() X* 4/26/91 Bill Norcott V1.06 -- tabulate results of a series X* of tests X* 5/17/91 Bill Norcott V1.07 -- use time() for VMS X* 5/20/91 Bill Norcott V1.08 -- use %ld for Turbo C and X* use #ifdef sun to bypass X* inclusion of limits.h X*/ X X/****************************************************************** X X INCLUDE FILES (system-dependent) X X******************************************************************/ X#ifdef __MSDOS__ /* Turbo C define this way for PCs... */ X#define MSDOS /* Microsoft C defines this */ X#endif X/* VMS and MS-DOS both have ANSI C compilers and use rand()/srand() */ X#ifdef VMS_POSIX X#undef VMS X#define ANSI_RANDOM 1 X#endif X#ifdef MSDOS X#define ANSI_RANDOM 1 X#endif X X/* incl definitions of O_* flags for XENIX */ X#ifdef M_XENIX X#include <fcntl.h> X#endif X/* SCO Unix System V */ X#ifdef M_UNIX X#include <sys/types.h> X#include <sys/fcntl.h> X#endif X X#if defined(VMS) X#define ANSI_RANDOM 1 X#include <math.h> X#include <unixio.h> X#include <ssdef.h> X#include <file.h> X#include <time.h> X X#elif defined(MSDOS) X#include <fcntl.h> X#include <time.h> X#elif defined(unix) X#include <sys/file.h> X#ifndef NULL X#define NULL 0 X#endif X/* Xdefine nolimits if your system has no limits.h. Sun's don't but I Xtake care of this explicitly beginning with V1.08 of IOzone. X*/ X#ifdef sun X#define nolimits X#define BSDtime X#endif X#ifndef nolimits X#include <limits.h> X#endif X#endif X/* for systems with System V-style time, define SysVtime */ X#ifdef M_SYSV X#define SysVtime X#endif X X#ifdef SysVtime X#include <sys/times.h> X#include <sys/param.h> X#ifndef CLK_TCK X#define CLK_TCK HZ X#endif X#endif X/* for systems with BSD style time, define BSDtime */ X#ifdef bsd4_2 X#define BSDtime X#endif X#ifdef BSDtime X#include <sys/time.h> X#endif X X X/****************************************************************** X X DEFINED CONSTANTS X X******************************************************************/ X#define MEGABYTES 1 /* number of megabytes in file */ X#define RECLEN 512 /* number of bytes in a record */ X#define FILESIZE (MEGABYTES*1024*1024) /*size of file in bytes*/ X#define NUMRECS FILESIZE/RECLEN /* number of records */ X#define MAXBUFFERSIZE 16*1024 /*maximum buffer size*/ X#define MINBUFFERSIZE 128 X#define TOOFAST 10 X#define USAGE "\tUsage:\tiozone [megabytes] [record_length_in_bytes] \ X[[path]filename]\n\n" X#define THISVERSION "V1.08" X X/* Define only one of the following two.*/ X/*#define NOTIME define if no time function in library*/ X#define TIME /*Use time(2)function*/ X#define MAXNAMESIZE 1000 /* max # of characters in filename */ X#define CONTROL_STRING1 "\t%-8ld%-8ld%-20ld%-20ld\n" X#define CONTROL_STRING2 "\t%-8s%-8s%-20s%-20s\n" X/* X For 'auto mode', these defines determine the number of iterations X to perform for both the file size and the record length. X I.e., if MEGABYTES_ITER_LIMIT = 5 use 1, 2, 4, 8 & 16 megabyte files X if RECLEN_ITER_LIMIT = 5 use 512, 1024, 2048, 4096 & 8192 byte records X*/ X#define MEGABYTES_ITER_LIMIT 5 X#define RECLEN_ITER_LIMIT 5 X X/****************************************************************** X X FUNCTION DECLARATIONS X X******************************************************************/ Xvoid auto_test(); /* perform automatic test series */ Xstatic double time_so_far(); /* time since start of program */ X/****************************************************************** X X GLOBAL VARIABLES X X******************************************************************/ Xint auto_mode; X X/****************************************************************** X X MAIN -- entry point X X******************************************************************/ Xmain(argc,argv) X int argc; X char *argv[]; X{ Xint fd; Xchar filename [MAXNAMESIZE]; /* name of temporary file */ Xchar *default_filename="iozone.tmp"; /*default name of temporary file*/ X X#ifdef MSDOS Xchar *buffer; X#else Xchar buffer [MAXBUFFERSIZE]; /*a temporary data buffer*/ X#endif Xint i, status; Xunsigned long megabytes = MEGABYTES, goodmegs; Xunsigned long reclen = RECLEN, goodrecl; Xunsigned long filesize = FILESIZE; Xunsigned long numrecs = NUMRECS; Xunsigned long filebytes; Xunsigned long readrate, writerate; X#ifdef TIME X double starttime1, starttime2; X double writetime, readtime; X double totaltime; X X#endif X X#ifdef MSDOS X buffer = (char *) calloc(1, MAXBUFFERSIZE); X#endif X X if (!auto_mode) X { X printf("\n\tIOZONE: Performance Test of Sequential File I/O -- %s\n", X THISVERSION); X printf("\t\tBy Bill Norcott\n\n"); X } X strcpy(filename,default_filename); X switch (argc) { X case 1: /* no args, take all defaults */ X printf(USAGE); X break; X case 2: /* <megabytes|filename> */ X i = atoi(argv[1]); if (i) { X megabytes = i; X } else { X/* X'Auto mode' will be enabled if the first command line argument is Xthe word 'auto'. This will trigger a series of tests X*/ X if ( (strcmp(argv[1], "auto") == 0) || X (strcmp(argv[1], "AUTO") == 0) ) X { X auto_mode = 1; X auto_test(); X printf("Completed series of tests\n"); X exit(0); X } else { X auto_mode = 0; X } X strcpy(filename,argv[1]); X } X break; X case 3: /* <megabytes> <reclen|filename> */ X megabytes = atoi(argv[1]); X if (atoi(argv[2])) { X reclen = atoi(argv[2]); X } else { X strcpy(filename,argv[2]); X } X break; X case 4: /* <megabytes> <reclen> <filename> */ X megabytes = atoi(argv[1]); X reclen = atoi(argv[2]); X strcpy(filename,argv[3]); X break; X default: X printf(USAGE); X exit(1); X X } X if (!auto_mode) X { X printf("\tSend comments to:\tBill.Norcott@nuo.mts.dec.com\n\n"); X } X filesize = megabytes*1024*1024; X numrecs = filesize/reclen; X if (reclen > MAXBUFFERSIZE) { X printf("Error: Maximum record length is %d bytes\n", MAXBUFFERSIZE); X exit(1); X } X if (reclen < MINBUFFERSIZE) { X printf("Error: Minimum record length is %d bytes\n", MINBUFFERSIZE); X exit(1); X } X if (!auto_mode) X { X printf("\tIOZONE writes a %ld Megabyte sequential file consisting of\n", X megabytes); X printf("\t%ld records which are each %ld bytes in length.\n", X numrecs, reclen); X printf("\tIt then reads the file. It prints the bytes-per-second\n"); X printf("\trate at which the computer can read and write files.\n\n"); X printf("\nWriting the %ld Megabyte file, '%s'...", megabytes, filename); X } X if((fd = creat(filename, 0640))<0){ X printf("Cannot create temporary file\n"); X exit(1); X } X#ifdef TIME X starttime1 = time_so_far(); X#endif X for(i=0; i<numrecs; i++){ X#ifndef DEBUG_ME X if(write(fd, buffer, (unsigned) reclen) != reclen) X { X printf("Error writing block %d\n", i); X exit(1); X } X#endif X } X X#ifdef TIME X writetime = time_so_far() - starttime1; X if (!auto_mode) X { X printf("%f seconds", writetime); X } X#endif X close(fd); X#if defined (VMS) X if((fd = open(filename, O_RDONLY, 0640))<0){ X printf("Cannot open temporary file for read\n"); X exit(1); X } X#elif defined(MSDOS) X if((fd = open(filename, O_RDONLY, 0640))<0){ X printf("Cannot open temporary file for read\n"); X exit(1); X } X#else X if((fd = open(filename, O_RDONLY))<0){ X printf("Cannot open temporary file for read\n"); X exit(1); X } X#endif X X X /*start timing*/ X#if defined(NOTIME) X printf("start timing\n"); X#endif X if (!auto_mode) X { X printf("\nReading the file..."); X } X starttime2 = time_so_far(); X for(i=0; i<numrecs; i++) { X#ifndef DEBUG_ME X if(read(fd, buffer, (unsigned) reclen) != reclen) X { X printf("Error reading block %d\n", i); X exit(1); X } X#endif X } X#ifdef NOTIME X printf("stop timing\n"); X#endif X#ifdef TIME X readtime = time_so_far() - starttime2; X if (!auto_mode) X { X printf("%f seconds\n", readtime); X } X#ifdef DEBUG_ME X readtime = 1; X writetime = 1; X#endif X if(readtime!=0) X { X filebytes = numrecs*reclen; X readrate = (unsigned long) ((double) filebytes / readtime); X writerate = (unsigned long) ((double) filebytes / writetime); X if (auto_mode) X { X printf(CONTROL_STRING1, X megabytes, X reclen, X writerate, X readrate); X X } else { X printf("\nIOZONE performance measurements:\n"); X printf("\t%ld bytes/second for writing the file\n", writerate); X printf("\t%ld bytes/second for reading the file\n", readrate); X totaltime = readtime + writetime; X if (totaltime < TOOFAST) X { X goodmegs = (TOOFAST/totaltime)*2*megabytes; X printf("\nThe test completed too quickly to give a good result\n"); X printf("You will get a more precise measure of this machine's\n"); X printf("performance by re-running IOZONE using the command:\n"); X printf("\n\tiozone %ld ", goodmegs); X printf("\t(i.e., file size = %ld megabytes)\n", goodmegs); X } X } X } else { X goodrecl = reclen/2; X printf("\nI/O error during read. Try again with the command:\n"); X printf("\n\tiozone %ld %ld ", megabytes, goodrecl); X printf("\t(i.e. record size = %ld bytes)\n", goodrecl); X } X#endif X close(fd); X#ifndef VMS X unlink(filename); /* delete the file */ X /*stop timer*/ X#endif X#ifdef MSDOS X free(buffer); /* deallocate the memory */ X#endif X#ifdef VMS Xreturn SS$_NORMAL; X#else Xreturn 0; X#endif X} X/****************************************************************** X X AUTO TEST -- perform series of tests and tabulate results X X******************************************************************/ Xvoid auto_test() X{ X int megsi, recszi; X char megs[10]; X char recsz[10]; X int i,j; X int argc = 3; X char *argv[3]; X X printf(CONTROL_STRING2, X "MB", X "reclen", X "bytes/sec written", X "bytes/sec read"); X argv[0] = "IOzone auto-test"; X argv[1] = megs; X argv[2] = recsz; X/* XStart with file size of 1 megabyte and repeat the test MEGABYTES_ITER_LIMIT Xtimes. Each time we run, the file size is doubled X*/ X for(i=0,megsi=1;i<MEGABYTES_ITER_LIMIT;i++,megsi*=2) X { X sprintf(megs, "%d", megsi); X/* XStart with record size of 512 bytes and repeat the test RECLEN_ITER_LIMIT Xtimes. Each time we run, the record size is doubled X*/ X for (j=0,recszi=512;j<RECLEN_ITER_LIMIT;j++,recszi*=2) X { X sprintf(recsz, "%d", recszi); X main(argc, argv); X } X } X} X Xstatic double Xtime_so_far() X{ X#if defined(VMS) X/* X* 5/17/91 Bill Norcott V1.07 -- use time() for VMS XThe times() function in VMS returns proc & user CPU time in 10-millisecond Xticks. Instead, use time() which lacks the precision but gives clock Xtime in seconds. X*/ X X return (double) time(NULL); X X#elif defined(SysVtime) X int val; X struct tms tms; X X if ((val = times(&tms)) == -1) X perror("times"); X X return ((double) val) / ((double) CLK_TCK); X#elif defined(MSDOS) X return ((double) clock()) / ((double) CLK_TCK); X#else X struct timeval tp; X X if (gettimeofday(&tp, (struct timezone *) NULL) == -1) X perror("gettimeofday"); X return ((double) (tp.tv_sec)) + X (((double) tp.tv_usec) / 1000000.0); X#endif X} END_OF_FILE if test 14433 -ne `wc -c <'iozone.c'`; then echo shar: \"'iozone.c'\" unpacked with wrong size! fi # end of 'iozone.c' fi echo shar: End of archive. exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.