[comp.arch] IOStone: A Synthetic File System Performance Benchmark

eugene@pioneer.arpa (Eugene Miya N.) (10/20/87)

Recently, the IOcall benchmark has become popular.  During a recent
visit to the Stanford CS Libray and a chance meeting at SIGMETRICS,
I came across this interesting paper.  In it, Arvin Park and Richard
Lipton present the attached program as an interesting "benchmark."
(These are the people with the "Massive Memory (sic)" machine.
I have problems with IOStone [so don't tell me how bogus you think this
thing is, Arvin and I already know], but I have agreed to post it for Arvin and
collect results for him [he is no longer at Princeton].  Please observe
the commentary about sending conditions.  I have one hardcopy of the
report dated January 1987 (with VAX 750, 785, 8600, Pyramid 90x, SUN 2
(with and without disk), and PC/AT.  I will post results as I collect it
and will send a hardcopy of the report (there are figures and graphs)
provided I get a US snail address.

On another disk note, I have been asked to post something further on
disk striping for `anonymous.'  I am not an I/O expert, but due to the
amount of mail I received, I am willing to set up an alias here on
pioneer for a short while on the topic. If interested, send mail address.

From the Rock of Ages Home for Retired Hackers:

--eugene miya
  NASA Ames Research Center
  eugene@ames-aurora.ARPA
  "You trust the `reply' command with all those different mailers out there?"
  "Send mail, avoid follow-ups.  If enough, I'll summarize."
  {hplabs,hao,ihnp4,decwrl,allegra,tektronix}!ames!aurora!eugene

----------cut here-------------------------

/*
*	"I/O Stone" Benchmark Program
*
*	Written by:	Arvin Park (park@princeton)
*		Department of Computer Science
*		Princeton University
*		Princeton, New Jersey 08544
*		(609) 452-6304 [--enm: no longer this phone or address]
*
*	Version:  C/1
*	Date:  12/10/86
*
*	Defines: If your version of "C" does not include a time(2)
*		function, define NOTIME. Use a stopwatch to measure
*		elapsed wall time.  Divide 400000 by the elapsed time
*		to get the correct number of iostones/second.
*
*	To compile:  cc -O io.c -o io
*
*	Note:	[1] This program should be run without other processes
*		competing for system resources.  Run it in the dead of
*		night if you have to.
*
*		[2] This program uses 4 megabytes of disk space.  Make
*		sure that at least this much space is available on
*		your file system before you run the program.
*
*		Results: If you get results from a new (machine/operating
*		system/disk controller and drive) combination please
*		send them to park@princeton.  Please include complete

*		********* no! send them to eugene@ames-aurora.arpa*****
*		********* do not bother Arvin as he is no longer @princeton

*		information on the machine type, operating system,
*		version, disk controller, and disk drives.  Also make
*		a note of any system modifications that have been
*		performed.
*/

#define FILESIZE (4L*1024L*1024L)	/*size of file in bytes*/
#define MAXBUFFERSIZE (64L*1024L)	/*maximum buffer size*/
#define NBLOCKSIZES 9			/*number of different block sizes*/
#define SEED 34710373L			/*random number generator seed*/
#define CONST 100000L			/*iostone normalization constant*/
#define ITER 4 				/*number of iterations of the code*/
/* Define only one of the following two.*/
/*#define NOTIME			/*define if no time function in library*/
#define TIME				/*Use time(2)function*/

char buffer [MAXBUFFERSIZE];		/*a temporary data buffer*/
char *filename="/tmp/iostone_temp_file"; /*name of temporary file*/
unsigned int nbytes;			/*number of bytes transferred*/
int fd;					/*file descriptor*/
long offset;				/*file offset*/
int i,j,k;				/*counter variables*/
long bsize [NBLOCKSIZES];		/*array for different block sizes*/
int bfreq [NBLOCKSIZES];		/*number of accesses for each block*/

#ifdef TIME
 long time();
 long starttime;
 long totaltime;
#endif

main() {
	init();
					/*start timing*/
#ifdef NOTIME
	printf("start timing\n");
#endif
#ifdef TIME
	starttime = time(0);
#endif

	for(k=0; k<ITER; k++)		/*perform string of file operations*/
		readswrites();
					/*stop timer*/
#ifdef NOTIME
	printf("stop timing\n");
#endif
#ifdef TIME
	totaltime = time(0) - starttime;
	printf("total time = %ld\n", totaltime);
	if(totaltime!=0)
		printf("This machine benchmarks at %ld iostones/second\n",
		(long) (CONST*ITER)/totaltime);
#endif
}

init(){
		/* create a temporary file*/
	if((fd = creat(filename, 0640))<0){
		printf("init: Cannot create temporary file\n");
		exit(1);
	}
		/*To both read and write the file*/
		/*it must be closed then opened*/
	close(fd);
	if((fd = open(filename,2))<0){
		printf("init: Cannot open temporary file\n");
		exit(1);
	}
			/*Unlink the file so that it will*/
			/*disappear when the program*/
			/*terminates.*/
	unlink(filename);

	lseek(fd,0L,0);	/*write initial portion of file*/
	for(i=0; i<(FILESIZE)/4096; i++){
		if((nbytes = write(fd, buffer, 4096))<0){
			printf("init: error writing block\n");
			exit(1);
 		}
	}

			/*set file block sizes and access*/
			/*frequencies.*/
	bsize[0] = 256; bfreq[0] = 128;
	bsize[1] = 512; bfreq[1] = 64;
	bsize[2] = 1024; bfreq[2] = 64;
	bsize[3] = 2048; bfreq[3] = 64;
	bsize[4] = 4096; bfreq[4] = 32;
	bsize[5] = 8192; bfreq[5] = 16;
	bsize[6] = 16384; bfreq[6] = 8;
	bsize[7] = 32768; bfreq[7] = 4;
	bsize[8] = 65536; bfreq[8] = 4;

	random(SEED);	/*initialize random number generator*/
}

readswrites(){
	for(j=0; j<NBLOCKSIZES; j++){
		for(i=0; i<bfreq[j]; i++){
			offset=(long) ((random()%(FILESIZE/bsize[j]))*bsize[j]);
			lseek(fd,offset,0);
			if((nbytes = read(fd, buffer, bsize[j]))<0){
				printf("readwrites: read error\n");
				exit(1);
			}
			offset=(long) ((random()%(FILESIZE/bsize[j]))*bsize[j]);
			lseek(fd, offset, 0);
			if((nbytes = read(fd, buffer, bsize[j]))<0){
				printf("readswrites: read error\n");
				exit(1);
			}
			offset=(long) ((random()%(FILESIZE/bsize[j]))*bsize[j]);
			lseek(fd, offset, 0);
			if((nbytes = write (fd, buffer, bsize [j]))<0){
				printf("readswrites: write error\n");
				exit(1);
			}
		}
	}
}