home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * "I/O Stone" Benchmark Program
- *
- * Written by: Arvin Park (park@midas.ucdavis.edu) and
- * Jeff Becker (becker@iris.ucdavis.edu)
- * Division of Computer Science
- * University of California, Davis
- * Davis CA 95616
- * (916) 752-5183
- *
- * Version C/II
- * Date: 06/27/90
- *
- * Defines: If your version of "C" does not include an ftime()
- * function or the C library time.h, define NOTIME.
- * Use a stopwatch to measure elapsed wall time.
- * Divide 2,000,000 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 5 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 becker@iris.ucdavis.edu. Please include
- * complete 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.
- *
- *-------------------------------------------------------------------------
- * 8/26/91 Tin Le
- * Added simple Makefile.
- *
- * As far as I can determine from examining the code, iostone is
- * meant for benchmarking file I/O and buffer cache efficiencies.
- *
- * It does this by creating NSETS (4) of SET_SIZE (99) files. Then
- * iostone performs I/O on each file in each set. The type of I/O is
- * randomly picked (r/w).
- *
- *--------------------------------------------------------------------------
- * 7/21/93 Oddgeir Kvien, kvien@elkraft.unit.no
- *
- * Slightly modified to compile with Borland C++ for OS/2
- *
- *--------------------------------------------------------------------------
- * 11/93 Jeffrey Patten 1:2410/242@fidonet.org
- *
- * IOStone gets chopped to pieces to adapt it as a portion of a
- * multithreaded disk/cpu usage benchmark. The numbers generated
- * are -NOT- comparable to those generated by the original program.
- * No attempt was made to maintain portability - my programming skills
- * are not yet advanced enough for that.
- *
- *--------------------------------------------------------------------------
- */
-
- #define INCL_NOPMAPI
- #define INCL_DOS
- #include <os2.h>
-
- #include "MDisk.h"
-
- #include <dir.h>
- #include <stdio.h>
- #include <io.h>
- #include <string.h>
- #include <time.h>
- #include <stdlib.h>
-
- /* PREDEFINISJON */
- int my_rand( int max );
- void initfile( char *fname, long fsize, PDTV pDisk );
- void readswrites( PDTV pDisk );
-
- void EndItAll( int rc, PDTV pDisk );
-
-
- VOID APIENTRY ThdDskPerf( ULONG ulTask )
- {
- int k;
- PDTV pDisk;
-
- pDisk = (PDTV)ulTask;
-
- pDisk->szDir[ 6 ] = (char)( pDisk->ulTask + 0x30 );
- pDisk->szDir[ 7 ] = 0;
-
- setdisk( (int)( pDisk->szDrive[ 0 ] - 'A' ) );
- mkdir( pDisk->szDir );
- chdir( pDisk->szDir );
-
- /* create test files */
- DosPostEventSem( pDisk->hevReady );
-
- /* start timing */
- DosWaitEventSem( hevGo, SEM_INDEFINITE_WAIT );
-
- /* perform string of file operations */
- for( k = 0; k < ITER; k++ )
- readswrites( pDisk );
-
- /*stop timimg*/
- EndItAll( 0, pDisk );
- }
-
- void init( PDTV pDisk )
- {
- int this_set; /*mark the file set (0..NSETS-1)*/
- int bcount; /*counter to track #spacer files*/
- int fcount; /*a counter to tell where to create*/
- int i, j, k; /*files to flush buffer cache and*/
- /*spread other files across disk*/
- pDisk->bsize[ 0 ] = 256; pDisk->bfreq[ 0 ] = 128;
- pDisk->bsize[ 1 ] = 512; pDisk->bfreq[ 1 ] = 64;
- pDisk->bsize[ 2 ] = 1024; pDisk->bfreq[ 2 ] = 64;
- pDisk->bsize[ 3 ] = 2048; pDisk->bfreq[ 3 ] = 64;
- pDisk->bsize[ 4 ] = 4096; pDisk->bfreq[ 4 ] = 32; /*set file block sizes and*/
- pDisk->bsize[ 5 ] = 8192; pDisk->bfreq[ 5 ] = 32; /*access frequencies*/
- pDisk->bsize[ 6 ] = 16384; pDisk->bfreq[ 6 ] = 8;
- pDisk->bsize[ 7 ] = 32768; pDisk->bfreq[ 7 ] = 2;
- pDisk->bsize[ 8 ] = 65536; pDisk->bfreq[ 8 ] = 2;
-
- k = 0; /*set up files*/
- bcount = 0;
- fcount = 0;
- for( i = 0; i < NBLOCKSIZES; i++ )
- {
- for( j = 0; j < pDisk->bfreq[ i ]; j++ )
- {
- if( i < NBLOCKSIZES - 1 )
- this_set = j % NSETS;
- else
- this_set = ( j + 2 ) % NSETS;
- sprintf( pDisk->tmp, "%0d_%0d", i, j ); /*create filename*/
- pDisk->files[ this_set ][ k ] = malloc( 1 + strlen( pDisk->tmp ));
- if( ! pDisk->files[ this_set ][ k ] )
- {
- printf( "Could not allocate string for filename\n" );
- EndItAll( 1, pDisk );
- }
- strcpy( pDisk->files[ this_set ][ k ], pDisk->tmp );
- initfile( pDisk->tmp, pDisk->bsize[ i ], pDisk );
- if( i < NBLOCKSIZES - 1 && this_set == NSETS - 1 )
- k++;
- if( bcount < NBFLUSH_FILES && fcount % 44 == 0 )
- {
- sprintf( pDisk->tmp, "%bf_%0d", bcount ); /*create spacer file*/
- pDisk->buf_flush_files[ bcount ] = malloc( 1 + strlen( pDisk->tmp ));
- if( ! pDisk->buf_flush_files[ bcount ] )
- {
- printf( "Could not allocate string for filename\n" );
- EndItAll( 1, pDisk );
- }
- strcpy( pDisk->buf_flush_files[ bcount ], pDisk->tmp );
- initfile( pDisk->tmp, BFLUSH_FILE_SIZE, pDisk );
- bcount++;
- }
- fcount++;
- }
- }
-
- for( i = 0; i < NBFLUSH_FILES; i++ )
- { /*read spacer files to flush buffers*/
- if( ( pDisk->fd = open( pDisk->buf_flush_files[ i ], 2)) < 0 )
- {
- printf( "error opening buffer flush file\n" );
- EndItAll( 1, pDisk );
- }
- lseek( pDisk->fd, 0L, 0 );
- k = BFLUSH_FILE_SIZE / BUFFERSIZE;
- for( j = 0; j < k; j++ )
- {
- if( ( pDisk->nbytes = read( pDisk->fd, pDisk->buffer, BUFFERSIZE )) < 0 )
- {
- printf( "Error reading buffer flush file\n" );
- EndItAll( 1, pDisk );
- }
- }
- close( pDisk->fd );
- }
-
- srand( SEED ); /*initialize random number generator*/
- for( i = 0; i < NSETS; i++ )
- { /*permutation for reading/writing*/
- for( j = SET_SIZE; j > 0; j-- )
- {
- k = my_rand( j );
- strcpy( pDisk->tmp, pDisk->files[ i ][ j - 1 ] );
- strcpy( pDisk->files[ i ][ j - 1 ], pDisk->files[ i ][ k ] );
- strcpy( pDisk->files[ i ][ k ], pDisk->tmp );
- }
- }
- }
-
- int my_rand( int max )
- {
- return rand() % max;
- }
-
-
- void initfile( char *fname, long fsize, PDTV pDisk )
- { /*create a temporary file*/
- FILE *fs;
- int block, num_blocks;
-
- if(( fs = fopen( fname, "w" )) == NULL )
- {
- printf( "init: Cannot create temporary file\n" );
- EndItAll( 1, pDisk );
- }
- rewind( fs ); /*write initial portion of file*/
- if( fsize > BUFFERSIZE )
- {
- num_blocks = fsize / BUFFERSIZE;
- for( block = 0; block < num_blocks; block++ )
- {
- if( ( pDisk->nbytes = fwrite( pDisk->buffer, 1, BUFFERSIZE, fs)) < 0 )
- {
- printf( "init: error writing block\n" );
- EndItAll( 1, pDisk );
- }
- }
- }
- else
- {
- if( ( pDisk->nbytes = fwrite( pDisk->buffer, 1, fsize, fs )) < 0 )
- {
- printf( "init: error writing block\n ");
- EndItAll( 1, pDisk );
- }
- }
- fclose( fs );
- }
-
- void readswrites( PDTV pDisk )
- {
- int i, j;
- int xfer, num_xfer; /*to access buffer correct # times*/
- long xfer_amt; /*amount to transfer to/from buffer*/
- int fsize_index; /*file size index (0..8)*/
- int rnum; /*rand. num to choose read or write*/
- int rep1, rep2; /*indices to loop through each file*/
- /*set twice, and all sets three times*/
-
- for( rep1 = 0; rep1 < 3; rep1++ )
- { /*in order to achieve locality which*/
- for( i = 0; i < NSETS; i++ )
- { /*is consistent with buffer cache data*/
- for( rep2 = 0; rep2 < 2; rep2++ )
- { /*of Ousterhout et al (1985)*/
- for( j = 0; j < SET_SIZE; j++ )
- {
- if( ( pDisk->fd = open( pDisk->files[ i ][ j ], 2)) < 0 )
- {
- printf( "readswrites: cannot open file\n" );
- EndItAll( 1, pDisk );
- }
- fsize_index = *( pDisk->files[ i ][ j ] ) - '0'; /*max xfer_amt = BUFFERSIZE*/
- if( pDisk->bsize[ fsize_index ] >= BUFFERSIZE )
- {
- num_xfer = pDisk->bsize[ fsize_index ] / BUFFERSIZE;
- xfer_amt = BUFFERSIZE;
- }
- else
- {
- num_xfer = 1;
- xfer_amt = pDisk->bsize[ fsize_index ];
- }
- rnum = my_rand( 3 );
- if( rnum < 2 )
- { /*read:write = 2:1*/
- lseek( pDisk->fd, 0L, 0 );
- for( xfer = 0; xfer < num_xfer; xfer++ )
- {
- if( ( pDisk->nbytes = read( pDisk->fd, pDisk->buffer, xfer_amt)) < 0 )
- {
- printf( "readswrites %d: read error\n", pDisk->ulTask );
- EndItAll( 1, pDisk );
- }
- }
- }
- else
- {
- lseek( pDisk->fd, 0L, 0 );
- for( xfer = 0; xfer < num_xfer; xfer++ )
- {
- if( ( pDisk->nbytes = write( pDisk->fd, pDisk->buffer, xfer_amt)) < 0 )
- {
- printf( "readswrites %d: write error\n", pDisk->ulTask );
- EndItAll( 1, pDisk );
- }
- }
- }
- close( pDisk->fd );
- }
- }
- }
- }
- }
-
- void EndItAll( int rc, PDTV pDisk )
- {
- pDisk->ulCount = ( CONST * ITER );
- pDisk->iExitCode = rc;
- DosPostEventSem( pDisk->hevDone );
-
- DosExit( 0, rc );
- }
-
-
- void removefiles( PDTV pDisk )
- {
- int i, j, k;
-
- /*remove files*/
- for( i = 0; i < NSETS; i++ )
- for( j = 0; j < SET_SIZE; j++ )
- unlink( pDisk->files[ i ][ j ] );
-
- for( k = 0; k < NBFLUSH_FILES; k++ )
- unlink( pDisk->buf_flush_files[ k ] );
-
- chdir( "\\" );
- rmdir( pDisk->szDir );
- }
-
-