v20i019: iozone - sequential file I/O benchmark for UNIX, VMS & DOS, Part01/01
Bill Norcott
norcott at databs.enet.dec.com
Sat May 25 07:25:31 AEST 1991
Submitted-by: Bill Norcott <norcott at 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 at uunet.uu.net if you want that tool.
# Contents: iozone.c
# Wrapped by kent at 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 at 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 at 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 at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list