[comp.sources.misc] v20i075: iozone1.09 - sequential file I/O benchmark, Part01/01

norcott@databs.enet.dec.com (Bill Norcott) (06/30/91)

Submitted-by: Bill Norcott <norcott@databs.enet.dec.com>
Posting-number: Volume 20, Issue 75
Archive-name: iozone1.09/part01
Environment: UNIX, VMS, DOS
Supersedes: iozone: Volume 20, Issue 19

Attached is iozone.c V1.09.  This is the latest version of my portable
benchmark of sequential file I/O.  This now supports over a dozen different
hardware/OS combinations.

New for this version is the help option, invoked by 'iozone help'

As always I welcome comments, your results from the 'iozone auto' test,
and modifications #include statements for systems not yet supported by
IOzone.

Regards,
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 Thu Jun 27 11:34:51 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'\" \(17184 characters\)
  sed "s/^X//" >'iozone.c' <<'END_OF_FILE'
X/*
X    iozone.c
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*/
Xchar *help[] = {
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" 	NOTE: as of V1.04 default file size is now 1 MB not 4 MB",
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"  For V1.09 you can show the development help by typing 'iozone help'",
X"        ",
X"  This program has been ported and tested on the following computer",
X"  operating systems:",
X" ",
X"    Vendor		Operating System    Notes on compiling IOzone",
X"    -------------------------------------------------------------------------",
X"    Convergent		Unisys/AT&T Sys5r3  cc -DCONVERGENT -o iozone iozone.c",
X"    Digital Equipment	ULTRIX V4.1 ",	
X"    Digital Equipment	VAX/VMS V5.4	    see below **	 ",
X"    Digital Equipment	VAX/VMS (POSIX) ",
X"    Hewlett-Packard	HP-UX 7.05",
X"    IBM    		AIX Ver. 3 rel. 1   cc -Dunix -o iozone iozone.c",
X"    Microsoft		MS-DOS 3.3	    tested Borland, Microsoft C",
X"    OSF    		OSF/1",
X"    SCO    		UNIX System V/386 3.2.2",
X"    SCO    		XENIX 3.2",
X"    Silicon Graphics	UNIX		    cc -DSGI -o iozone iozone.c",
X"    Sun Microsystems	SUNOS 4.1.1",
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, Jody Winston, Clarence Dold",
X"        ",
X"  --- MODIFICATION HISTORY:",
X" ",
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"    6/19/91 Bill Norcott	V1.09 -- rid #elif to support HP-UX and ",
X" 					Silicon Graphics UNIX, and",
X" 					add #ifdef SGI",
X" 					add #ifdef CONVERGENT",
X"					for Convergent Technologies",
X" 					also add help option",
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/* Convergent Technologies M680xx based with Unisys/AT&T Sys5r3 */
X#ifdef CONVERGENT
X#include <fcntl.h>
X#define SysVtime
X#endif 
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#else
X#ifdef MSDOS
X/* #elif defined(MSDOS) */
X#include <fcntl.h>
X#include <time.h>
X#endif
X/* #elif defined(unix) */
X#ifdef unix
X#include <sys/file.h>
X#ifndef NULL
X#define NULL 0
X#endif
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/* V1.09 -- Silicon Graphics compile with -DSGI  */
X#ifdef SGI
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\t\tiozone auto\n\t\tiozone help\n\n"
X#define THISVERSION "V1.09"
X 
X/* Define only one of the following two.  All modern operating systems
Xhave time functions so let TIME be defined */
X#if 1
X#define TIME 1
X#else
X#define NOTIME 1
X#endif
X
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 */
Xvoid show_help();		/* show development help*/
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	  if ( (strcmp(argv[1], "help") == 0) || 
X	       (strcmp(argv[1], "HELP") == 0) )
X	  {
X	    show_help();
X	    exit(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("IOzone: bad usage\n");
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#else
X#ifdef MSDOS
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#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    SHOW HELP -- show development help of this program
X 
X******************************************************************/
Xvoid show_help()
X{
X    int i;
X    printf("iozone: help mode\n\n");
X    for(i=0; strlen(help[i]); i++)
X    {
X	printf("%s\n", help[i]);
X    }
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("iozone: auto-test mode\n\n");
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#else
X#ifdef SysVtime
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#endif
X#if defined(MSDOS)
X  return ((double) clock()) / ((double) CLK_TCK);
X#endif
X#ifndef MSDOS
X#ifndef SysVtime
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#endif
X#endif
X}
X
END_OF_FILE
  if test 17184 -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.