[comp.sources.misc] v17i065: iozone - sequential file I/O benchmark fo UNIX, VMS & DOS, Part01/01

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.