norcott@databs.enet.dec.com (Bill Norcott) (03/23/91)
Submitted-by: Bill Norcott <norcott@databs.enet.dec.com> Posting-number: Volume 17, Issue 65 Archive-name: iozone/part01 Attached is a benchmark called IOzone which I have written. It was inspired by Alvin Park's IOstone benchmark (which tests random access I/O). IOzone tests sequential file I/O using the C language. It writes, then reads, a sequential file of fixed length records, and measures the read & write rates in bytes per second. The default is to create a 1 megabyte file consisting of 2048, 512-byte records -- however, these parameters can be changed from the command line. On UNIX systems, the results will be influenced by the effect of the buffer cache -- however, we can largely negate the effect of caching by using a file size greater than twice the size of the cache. This will allow a fairer comparison between various disk drives attached to the system. IOzone IS NOT a direct test of disk performance. Its results are a combination of disk speed, CPU speed, amount of cache, and the efficiency of the C compiler & runtime library. This is also true of IOstone, in fact I intend this program as a companion piece to IOstone. This benchmark is portable and has been tested on these operating systems: VAX/VMS V5.4 Ultrix V4.1 MS-DOS V3.1 OSF/1 IOZONE.C is free and in the public domain. I would appreciate your comment and test results. Bill Norcott (Bill.Norcott.nuo.mts.dec.com) ------------------------------ 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 Mar 22 15:25:03 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'\" \(7723 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* This is free software. License to freely use and distribute this X* software is hereby granted by the author, subject to the condition X* that this copyright notice remains intact." 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* 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. For UNIX systems I call fsync() to force X* the writes to disk. This gives a test of the time it takes to X* actually get data onto the disk. X* X* This program has been ported and tested on the following computer X* operating systems: X* VAX/VMS V5.4, Ultrix V4.1, OSF/1 and MS-DOS 3.3" X* X* --- MODIFICATION HISTORY: X* X* 3/7/91 William D. Norcott (Bill.Norcott@nuo.mts.dec.com) X* created X* 3/22/91 Bill Norcott tested on OSF/1 ... it works 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#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 X#elif defined(MSDOS) X#include <fcntl.h> X#elif defined(unix) X#include <sys/file.h> X#include <limits.h> X#endif 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 TOOFAST 10 X#define USAGE "\tUsage:\tiozone [megabytes] [record_length] [[path]filename]\n\n" X#define THISVERSION "V1.01" 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 X#define MAXNAMESIZE 1000 /* max # of characters in filename */ X Xmain(argc,argv) X int argc; X char *argv[]; X{ Xint fd; Xchar filename [MAXNAMESIZE]; /* name of temporary file */ X#ifdef VMS Xchar *default_filename="iozone_temp_file"; /*default name of temporary file*/ X#else X#ifdef MSDOS Xchar *default_filename="iozone.tmp"; /*default name of temporary file*/ X#else Xchar *default_filename="/tmp/iozone_temp_file"; /*default name of temporary file*/ X#endif X#endif 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; X X#ifdef TIME X long time(); X long starttime1, starttime2; X long writetime; X long totaltime; X X#endif X X#ifdef MSDOS X buffer = (char *) malloc(MAXBUFFERSIZE); X#endif 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 strcpy(filename,argv[1]); X } X break; X case 3: /* <megabytes> <reclen|filename> */ X filesize = atoi(argv[1]); X i = atoi(argv[2]); if(i) { X reclen = (unsigned) i; X } else { X strcpy(filename,argv[2]); X } X break; X case 4: /* <megabytes> <reclen> <filename> */ X filesize = 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 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 } 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#ifdef TIME X starttime1 = time(0); X#endif X if((fd = creat(filename, 0640))<0){ X printf("Cannot create temporary file\n"); X exit(1); X } X for(i=0; i<numrecs; i++){ X write(fd, buffer, (unsigned) reclen); X } X X#ifdef TIME X writetime = time(0) - starttime1; X printf("%d seconds", writetime); X#endif X close(fd); X#ifdef VMS X if((fd = open(filename, O_RDONLY, 0640))<0){ X printf("Cannot open temporary file for read\n"); X exit(1); 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#else X if((fd = open(filename, O_RDONLY))<0){ X printf("Cannot open temporary file for read\n"); X exit(1); X#endif X } X X /*start timing*/ X#ifdef NOTIME X printf("start timing\n"); X#endif X X printf("\nReading the file..."); X starttime2 = time(0); X for(i=0; i<numrecs; i++) { X if(read(fd, buffer, (unsigned) reclen) < 0) X perror("Read error"); X } X#ifdef NOTIME X printf("stop timing\n"); X#endif X#ifdef TIME X totaltime = time(0) - starttime2; X X printf("%d seconds\n", totaltime); X if(totaltime!=0) X { X printf("\nIOZONE performance measurements:\n"); X printf("\t%ld bytes/second for writing the file\n", X (long) ((numrecs*reclen)/writetime) ); X printf("\t%ld bytes/second for reading the file\n", X (long) ((numrecs*reclen)/totaltime) ); X if (totaltime < TOOFAST) { X goodmegs = (TOOFAST/totaltime)*2*megabytes; X printf("\nThis machine is fast (or is using a disk cache)!\n"); X printf("You will get a more accurate measure of its\n"); X printf("performance by re-running IOZONE using the command:\n"); X printf("\n\tiozone %d ", goodmegs); X printf("\t(i.e., file size = %d megabytes)\n", goodmegs); X } X } else { X goodrecl = reclen/2; X printf("\nI/O error during read. Try again with the command:\n"); X printf("\n\tiozone %d %d ",megabytes, (int) goodrecl); X printf("\t(i.e. record size = %d bytes)\n", (int) 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 END_OF_FILE if test 7723 -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.