home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
iostone2.zip
/
IOStone.c
next >
Wrap
Text File
|
1995-05-15
|
14KB
|
436 lines
/*
*
* "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/17/93 Ketil Kintel, kintel@hsr.no
*
* -Fixed bug with the file name generation for the spacer file.
* -Slightly modified to show some output while running. Users with slow
* systems will shurely appriciate this. (I do ...)
* This may cause IOStone to show a _slightly_ lower value than it would do
* normally. If you don't want it #define NOEXTRAOUTPUT
* -Added code for average read/write troughput.
* -Added code for number of file opens/closes.
* -Modified to compile on a 16bit compiler also (Bolrand C++ 3.11 DOS)
* An int ain't always an int...
*--------------------------------------------------------------
* 5/13/95 - Galen Rhodes <grhodes@moscow.com>
*
* -Bypassed the Borland Runtime in critical areas.
*
*/
#ifdef __OS2__
#define INCL_DOSFILEMGR
#define INCL_DOSMISC
#include <os2.h>
#endif
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <sys\stat.h>
#include <fcntl.h>
#define BFLUSH_FILE_SIZE (512L*1024L) /*size of files used to flush buffers*/
#define NBFLUSH_FILES 8 /*number of files used to flush buffers*/
#define NBLOCKSIZES 9 /*number of different block sizes*/
#define SEED 34710373L /*random number generator seed*/
#define CONST 500000L /*iostone normalization constant*/
#define ITER 4 /*number of iterations of the code*/
#define BUFFERSIZE (16L*1024L) /*size of temporary buffer*/
/* #define NOEXTRAOUTPUT 1 /* Define if you dont want the extra */
/* time consuming output while running. */
#define CR=13 /* Carriage Return on MS-DOS system */
/* define only one of the next three defines */
/*#define NOTIME /* Define if no time function in library */
/*#define TIME /* Use UNIX time function */
#define NON_UNIX_TIME 1 /* Use if a non-unix system */
#define NSETS 4 /*number of sets of files*/
#define SET_SIZE 99 /*number of files in each set*/
#define FNAMELEN 8 /*maximum file name length*/
/* char *malloc(); */
char tmp[FNAMELEN]; /*a temporary string*/
char *files[NSETS][SET_SIZE]; /*array of file names*/
char *buf_flush_files[NBFLUSH_FILES]; /*array of names of files to flush*/
/*system buffers*/
char buffer[BUFFERSIZE]; /*a temporary buffer*/
long int nbytes; /*number of bytes transfered*/
long int fd; /*file descriptor*/
long int i,j,k; /*counter variables*/
long bsize[NBLOCKSIZES]; /*array for different block sizes*/
long bfreq[NBLOCKSIZES]; /*number of accesses for each block*/
#ifdef TIME
#include <sys\types.h>
#include <sys\timeb.h>
struct timeb before;
struct timeb after;
long int sec;
long int msec;
#endif
#ifdef NON_UNIX_TIME
long int starttime;
long int totaltime;
#endif
/* PREDEFINISJON */
void init(void);
long int my_rand(int max);
void initfile(char *fname,long fsize);
void readswrites(void);
unsigned long int troughr; /* Counts number read IO bytes */
unsigned long int troughw; /* Counts number write IO bytes */
unsigned long int fileoc; /* Counts number of file opens/closes */
void main(void) {
printf("\nWait - IOSTONE is setting up test files:\t");
init();
printf("\rWait - IOSTONE is performing disk IO with varying blocksizes.\t\n");
/*start timing*/
#ifdef NOTIME
printf("start timing\n");
#endif
#ifdef TIME
ftime(&before);
#endif
#ifdef NON_UNIX_TIME
starttime = time(0);
#endif
for(k=0; k<ITER; k++) /*perform string of file operations*/
{
#ifndef NOEXTRAOUTPUT
printf("\r\t\t\t\t\t\t\rPass %d:\t",(k+1));
#endif
readswrites();
}
/*stop timimg*/
#ifdef NOTIME
printf("stop timing\n");
#endif
#ifdef TIME
ftime(&after);
sec = after.time - before.time;
msec = after.millitm - before.millitm;
if (msec < 0) { /*adjust if fractional time < 0*/
sec -= 1;
msec += 1000;
}
printf("\r\t\t\t\t\t\t\nTotal elapsed time is %d seconds and %d milliseconds.\n",sec,msec);
printf("Files were opened %u times. %u kb read. %u kb written. \n",
fileoc,((troughr+512)/1024),((troughw+512)/1024));
if (sec!=0 || msec!=0)
{
printf("Average read/write troughput was %.0f kb/sec, including open/close overhead.\n",
(((troughr+troughw)/((float) sec + (float) msec/1000)) + 0.5)/1024);
printf("\nThis machine benchmarks at %.0f iostones/sec.\n\n",
((float)(CONST*ITER)/((float) sec + (float) msec/1000)) + 0.5);
}
#endif
#ifdef NON_UNIX_TIME
totaltime = time(0) - starttime;
printf("\r\t\t\t\t\t\t\nTotal elapsed time is %ld sec.\n",totaltime); /* Uses multipple lines */
printf("Files were opened %u times.",fileoc); /* because of bug in BorlandC */
printf(" %u kb was read, and",((troughr+512)/1024));
printf(" %u kb written.\n",((troughw+512)/1024));
if (totaltime!=0)
{
printf("Average read/write troughput was %.0f kb/sec, including open/close overhead.\n",
(((troughr+troughw)/((float) totaltime)) + 0.5)/1024);
printf("\nThis machine benchmarks at %.0f iostones/sec.\n\n",
((float)(CONST*ITER)/((float) totaltime)) + 0.5);
}
#endif
for (i=0;i<NSETS;i++)
for (j=0;j<SET_SIZE;j++)
unlink(files[i][j]); /*remove files*/
for (k=0;k<NBFLUSH_FILES;k++)
unlink(buf_flush_files[k]);
}
void init(void) {
long int this_set; /*mark the file set (0..NSETS-1)*/
long int bcount; /*counter to track #spacer files*/
long int fcount; /*a counter to tell where to create*/
/*files to flush buffer cache and*/
/*spread other files across disk*/
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; /*set file block sizes and*/
bsize[5]=8192; bfreq[5]=32; /*access frequencies*/
bsize[6]=16384; bfreq[6]=8;
bsize[7]=32768; bfreq[7]=2;
bsize[8]=65536; bfreq[8]=2;
troughr=0;
troughw=0;
fileoc=0;
k=0; /*set up files*/
bcount=0;
fcount=0;
for(i=0;i<NBLOCKSIZES;i++) {
printf(".");
for(j=0;j<bfreq[i];j++) {
if (i<NBLOCKSIZES-1)
this_set = j%NSETS;
else
this_set = (j+2)%NSETS;
sprintf(tmp,"%0d_%0d",i,j); /*create filename*/
files[this_set][k] = malloc(1+strlen(tmp));
if (!files[this_set][k]) {
printf("Could not allocate string for filename\n");
exit(1);
}
strcpy(files[this_set][k],tmp);
initfile(tmp,bsize[i]);
if (i < NBLOCKSIZES-1 && this_set == NSETS-1) k++;
if (bcount < NBFLUSH_FILES && fcount%44 == 0) {
sprintf(tmp,"s_%0d",bcount); /*create spacer file*/
buf_flush_files[bcount] = malloc(1+strlen(tmp));
if (!buf_flush_files[bcount]) {
printf("Could not allocate string for filename\n");
exit(1);
}
strcpy(buf_flush_files[bcount],tmp);
initfile(tmp,BFLUSH_FILE_SIZE);
bcount++;
}
fcount++;
}
}
for(i=0;i<NBFLUSH_FILES;i++) { /*read spacer files to flush buffers*/
if ((fd = open(buf_flush_files[i],O_RDWR))<0) /* UNIX 2 */ {
printf("\nError opening buffer flush file %d of %d.\n",i+1,NBFLUSH_FILES);
exit(1);
}
lseek(fd,0L,0);
k = BFLUSH_FILE_SIZE/BUFFERSIZE;
for(j=0;j<k;j++) {
if((nbytes = read(fd,buffer,BUFFERSIZE))<0) {
printf("\nError reading buffer flush file %d of %d.\n",j+1,k);
exit(1);
}
}
close(fd);
}
#ifdef NON_UNIX_TIME
srand(SEED);
#else
srandom(SEED); /*initialize random number generator*/
#endif /*and order files in a random*/
for(i=0;i<NSETS;i++) { /*permutation for reading/writing*/
for(j=SET_SIZE;j>0;j--) {
k=my_rand(j);
strcpy(tmp,files[i][j-1]);
strcpy(files[i][j-1],files[i][k]);
strcpy(files[i][k],tmp);
}
}
}
long int my_rand(int max)
{
#ifdef NON_UNIX_TIME
return rand()%max;
#else
return random()%max;
#endif
}
void initfile(char *fname,long fsize)
{ /*create a temporary file*/
FILE *fs;
long int block, num_blocks;
if((fs=fopen(fname,"w"))==NULL){
printf("init: Cannot create temporary file\n");
exit(1);
}
rewind(fs); /*write initial portion of file*/
if (fsize > BUFFERSIZE) {
num_blocks=fsize/BUFFERSIZE;
for(block=0;block<num_blocks;block++) {
if ((nbytes=fwrite(buffer,1,BUFFERSIZE,fs))<0) {
printf("init: error writing block\n");
exit(1);
}
}
}
else {
if ((nbytes=fwrite(buffer,1,fsize,fs))<0) {
printf("init: error writing block\n");
exit(1);
}
}
fclose(fs);
}
void readswrites(void){
long int xfer, num_xfer; /*to access buffer correct # times*/
long int xfer_amt; /*amount to transfer to/from buffer*/
long int fsize_index; /*file size index (0..8)*/
long int rnum; /*rand. num to choose read or write*/
long int rep1,rep2; /*indices to loop through each file*/
/*set twice, and all sets three times*/
#ifdef __OS2__
HFILE hfFile;
ULONG ulAction;
ULONG ulLocal;
#endif
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)*/
#ifndef NOEXTRAOUTPUT
printf(".");
#endif
for(j=0;j<SET_SIZE;j++) {
#ifdef __OS2__
if(DosOpen(files[i][j],
&hfFile,
&ulAction,
0,
FILE_NORMAL,
FILE_OPEN,
OPEN_FLAGS_FAIL_ON_ERROR |
OPEN_FLAGS_RANDOMSEQUENTIAL |
OPEN_ACCESS_READWRITE |
OPEN_SHARE_DENYWRITE,
NULL)) /* OS/2 */ {
#else
if ((fd = open(files[i][j],O_RDWR))<0) /* UNIX 2 */ {
#endif
printf("readswrites: cannot open file[%d][%d]\n",i,j);
exit(1);
}
fileoc++; /* Counts number of file opens/closes */
fsize_index = *(files[i][j]) -'0'; /*max xfer_amt = BUFFERSIZE*/
if (bsize[fsize_index] >= BUFFERSIZE) {
num_xfer = bsize[fsize_index]/BUFFERSIZE;
xfer_amt = BUFFERSIZE;}
else {
num_xfer = 1;
xfer_amt = bsize[fsize_index];}
rnum = my_rand(3);
if (rnum < 2) { /*read:write = 2:1*/
#ifdef __OS2__
DosSetFilePtr(hfFile,0L,FILE_BEGIN,&ulLocal);
#else
lseek(fd,0L,0);
#endif
for (xfer=0; xfer<num_xfer; xfer++) {
troughr+=xfer_amt; /* Counts total read IO bytes*/
#ifdef __OS2__
if(DosRead(hfFile,buffer,xfer_amt,&nbytes)) {
#else
if((nbytes=read(fd,buffer,xfer_amt))<0) {
#endif
printf ("readswrites: read error[%d][%d]\n",i,j);
exit(1);
}
}
}
else {
#ifdef __OS2__
DosSetFilePtr(hfFile,0L,FILE_BEGIN,&ulLocal);
#else
lseek(fd,0L,0);
#endif
for (xfer=0; xfer<num_xfer; xfer++) {
troughw+=xfer_amt; /* Counts total write IO bytes*/
#ifdef __OS2__
if(DosWrite(hfFile,buffer,xfer_amt,&nbytes)) {
#else
if((nbytes=write(fd,buffer,xfer_amt))<0) {
#endif
printf ("readswrites: write error[%d][%d]\n",i,j);
exit(1);
}
}
}
#ifdef __OS2__
DosClose(hfFile);
#else
close(fd);
#endif
}
}
}
}
}