home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / iostone2.zip / IOStone.c next >
Text File  |  1995-05-15  |  14KB  |  436 lines

  1. /*
  2. *
  3. *   "I/O Stone" Benchmark Program
  4. *
  5. *   Written by: Arvin Park (park@midas.ucdavis.edu) and
  6. *            Jeff Becker (becker@iris.ucdavis.edu)
  7. *            Division of Computer Science
  8. *            University of California, Davis
  9. *            Davis CA 95616
  10. *            (916) 752-5183
  11. *
  12. *   Version C/II
  13. *   Date: 06/27/90
  14. *
  15. *   Defines: If your version of "C" does not include an ftime()
  16. *            function or the C library time.h, define NOTIME.
  17. *            Use a stopwatch to measure elapsed wall time.
  18. *            Divide 2,000,000 by the elapsed time to get
  19. *            the correct number of iostones/second.
  20. *
  21. *   To compile:   cc -O io.c -o io
  22. *
  23. *   Note:    [1] This program should be run without other processes
  24. *            competing for system resources. Run it in the dead of
  25. *            night if you have to.
  26. *
  27. *            [2] This program uses 5 megabytes of disk space. Make
  28. *            sure that at least this much space is available on
  29. *            your file system before you run the program.
  30. *
  31. *   Results: If you get results from a new (machine/operating
  32. *            system/disk controller and drive) combination, please
  33. *            send them to becker@iris.ucdavis.edu. Please include
  34. *            complete information on the machine type, operating
  35. *            system, version, disk controller, and disk drives.
  36. *            Also make a note of any system modifications that
  37. *            have been performed.
  38. *
  39. *-------------------------------------------------------------------------
  40. * 8/26/91 Tin Le
  41. *    Added simple Makefile.
  42. *
  43. *    As far as I can determine from examining the code, iostone is
  44. *    meant for benchmarking file I/O and buffer cache efficiencies.
  45. *
  46. *    It does this by creating NSETS (4) of SET_SIZE (99) files.  Then
  47. *    iostone performs I/O on each file in each set.  The type of I/O is
  48. *    randomly picked (r/w).
  49. *
  50. *--------------------------------------------------------------------------
  51. * 7/21/93 Oddgeir Kvien, kvien@elkraft.unit.no
  52. *
  53. * Slightly modified to compile with Borland C++ for OS/2
  54. *
  55. *--------------------------------------------------------------------------
  56. * 11/17/93 Ketil Kintel, kintel@hsr.no
  57. *
  58. * -Fixed bug with the file name generation for the spacer file.
  59. * -Slightly modified to show some output while running. Users with slow
  60. * systems will shurely appriciate this. (I do ...)
  61. * This may cause IOStone to show a _slightly_ lower value than it would do
  62. * normally. If you don't want it #define NOEXTRAOUTPUT
  63. * -Added code for average read/write troughput.
  64. * -Added code for number of file opens/closes.
  65. * -Modified to compile on a 16bit compiler also (Bolrand C++ 3.11 DOS)
  66. *  An int ain't always an int...
  67. *--------------------------------------------------------------
  68. * 5/13/95 - Galen Rhodes <grhodes@moscow.com>
  69. * -Bypassed the Borland Runtime in critical areas.
  70. *
  71. */
  72.  
  73. #ifdef __OS2__
  74. #define INCL_DOSFILEMGR
  75. #define INCL_DOSMISC
  76. #include <os2.h>
  77. #endif
  78.  
  79. #include <stdio.h>
  80. #include <io.h>
  81. #include <string.h>
  82. #include <time.h>
  83. #include <stdlib.h>
  84. #include <sys\stat.h>
  85. #include <fcntl.h>
  86.  
  87. #define BFLUSH_FILE_SIZE (512L*1024L)   /*size of files used to flush buffers*/
  88. #define NBFLUSH_FILES 8                 /*number of files used to flush buffers*/
  89. #define NBLOCKSIZES 9                   /*number of different block sizes*/
  90. #define SEED 34710373L                  /*random number generator seed*/
  91. #define CONST 500000L                   /*iostone normalization constant*/
  92. #define ITER 4                          /*number of iterations of the code*/
  93. #define BUFFERSIZE (16L*1024L)        /*size of temporary buffer*/
  94.  
  95. /* #define NOEXTRAOUTPUT 1    /* Define if you dont want the extra    */
  96.                             /* time consuming output while running. */
  97.  
  98. #define CR=13 /* Carriage Return on MS-DOS system */
  99.  
  100. /* define only one of the next three defines */
  101. /*#define NOTIME        /* Define if no time function in library */
  102. /*#define TIME            /* Use UNIX time function */
  103. #define NON_UNIX_TIME 1        /* Use if a non-unix system */
  104.  
  105. #define NSETS 4                         /*number of sets of files*/
  106. #define SET_SIZE 99                     /*number of files in each set*/
  107. #define FNAMELEN  8                     /*maximum file name length*/
  108.  
  109. /* char *malloc(); */
  110. char tmp[FNAMELEN];                     /*a temporary string*/
  111. char *files[NSETS][SET_SIZE];           /*array of file names*/
  112. char *buf_flush_files[NBFLUSH_FILES];   /*array of names of files to flush*/
  113.                                                      /*system buffers*/
  114. char buffer[BUFFERSIZE];                /*a temporary buffer*/
  115.  
  116. long int nbytes;                        /*number of bytes transfered*/
  117. long int fd;                                 /*file descriptor*/
  118. long int i,j,k;                              /*counter variables*/
  119. long bsize[NBLOCKSIZES];                /*array for different block sizes*/
  120. long bfreq[NBLOCKSIZES];                 /*number of accesses for each block*/
  121.  
  122. #ifdef TIME
  123. #include <sys\types.h>
  124. #include <sys\timeb.h>
  125. struct timeb before;
  126. struct timeb after;
  127. long int sec;
  128. long int msec;
  129. #endif
  130.  
  131. #ifdef NON_UNIX_TIME
  132. long int starttime;
  133. long int totaltime;
  134. #endif
  135.  
  136. /* PREDEFINISJON */
  137. void init(void);
  138. long int my_rand(int max);
  139. void initfile(char *fname,long fsize);
  140. void readswrites(void);
  141.  
  142. unsigned long int troughr; /* Counts number read IO bytes */
  143. unsigned long int troughw; /* Counts number write IO bytes */
  144. unsigned long int fileoc; /* Counts number of file opens/closes */
  145.  
  146. void main(void) {
  147.  
  148.   printf("\nWait - IOSTONE is setting up test files:\t");
  149.   init();
  150.   printf("\rWait - IOSTONE is performing disk IO with varying blocksizes.\t\n");
  151.                             /*start timing*/
  152. #ifdef NOTIME
  153.   printf("start timing\n");
  154. #endif
  155. #ifdef TIME
  156.   ftime(&before);
  157. #endif
  158. #ifdef NON_UNIX_TIME
  159.   starttime = time(0);
  160. #endif
  161.  
  162.   for(k=0; k<ITER; k++)            /*perform string of file operations*/
  163.   {
  164. #ifndef NOEXTRAOUTPUT
  165.     printf("\r\t\t\t\t\t\t\rPass %d:\t",(k+1));
  166. #endif
  167.     readswrites();
  168.   }
  169.                     /*stop timimg*/
  170. #ifdef NOTIME
  171.   printf("stop timing\n");
  172. #endif
  173. #ifdef TIME
  174.   ftime(&after);
  175.   sec = after.time - before.time;
  176.   msec = after.millitm - before.millitm;
  177.   if (msec < 0) {            /*adjust if fractional time < 0*/
  178.     sec -= 1;
  179.      msec += 1000;
  180.   }
  181.   printf("\r\t\t\t\t\t\t\nTotal elapsed time is %d seconds and %d milliseconds.\n",sec,msec);
  182.   printf("Files were opened %u times. %u kb read. %u kb written. \n",
  183.     fileoc,((troughr+512)/1024),((troughw+512)/1024));
  184.   if (sec!=0 || msec!=0)
  185.   {
  186.     printf("Average read/write troughput was %.0f kb/sec, including open/close overhead.\n",
  187.       (((troughr+troughw)/((float) sec + (float) msec/1000)) + 0.5)/1024);
  188.  
  189.      printf("\nThis machine benchmarks at %.0f iostones/sec.\n\n",
  190.         ((float)(CONST*ITER)/((float) sec + (float) msec/1000)) + 0.5);
  191.   }
  192.  
  193. #endif
  194. #ifdef NON_UNIX_TIME
  195.   totaltime = time(0) - starttime;
  196.   printf("\r\t\t\t\t\t\t\nTotal elapsed time is %ld sec.\n",totaltime); /* Uses multipple lines */
  197.   printf("Files were opened %u times.",fileoc);             /* because of bug in BorlandC */
  198.   printf(" %u kb was read, and",((troughr+512)/1024));
  199.   printf(" %u kb written.\n",((troughw+512)/1024));
  200.   if (totaltime!=0)
  201.   {
  202.     printf("Average read/write troughput was %.0f kb/sec, including open/close overhead.\n",
  203.       (((troughr+troughw)/((float) totaltime)) + 0.5)/1024);
  204.  
  205.     printf("\nThis machine benchmarks at %.0f iostones/sec.\n\n",
  206.         ((float)(CONST*ITER)/((float) totaltime)) + 0.5);
  207.   }
  208.  
  209. #endif
  210.   for (i=0;i<NSETS;i++)
  211.     for (j=0;j<SET_SIZE;j++)
  212.         unlink(files[i][j]);              /*remove files*/
  213.   for (k=0;k<NBFLUSH_FILES;k++)
  214.     unlink(buf_flush_files[k]);
  215. }
  216.  
  217. void init(void) {
  218.  
  219.   long int this_set;                         /*mark the file set (0..NSETS-1)*/
  220.   long int bcount;                           /*counter to track #spacer files*/
  221.   long int fcount;                           /*a counter to tell where to create*/
  222.                                         /*files to flush buffer cache and*/
  223.                                         /*spread other files across disk*/
  224.   bsize[0]=256; bfreq[0]=128;
  225.   bsize[1]=512; bfreq[1]=64;
  226.   bsize[2]=1024; bfreq[2]=64;
  227.   bsize[3]=2048; bfreq[3]=64;
  228.   bsize[4]=4096; bfreq[4]=32;           /*set file block sizes and*/
  229.   bsize[5]=8192; bfreq[5]=32;           /*access frequencies*/
  230.   bsize[6]=16384; bfreq[6]=8;
  231.   bsize[7]=32768; bfreq[7]=2;
  232.   bsize[8]=65536; bfreq[8]=2;
  233.  
  234.   troughr=0;
  235.   troughw=0;
  236.   fileoc=0;
  237.  
  238.   k=0;                                  /*set up files*/
  239.   bcount=0;
  240.   fcount=0;
  241.   for(i=0;i<NBLOCKSIZES;i++) {
  242.     printf(".");
  243.     for(j=0;j<bfreq[i];j++) {
  244.       if (i<NBLOCKSIZES-1)
  245.     this_set = j%NSETS;
  246.       else
  247.     this_set = (j+2)%NSETS;
  248.         sprintf(tmp,"%0d_%0d",i,j);       /*create filename*/
  249.         files[this_set][k] = malloc(1+strlen(tmp));
  250.       if (!files[this_set][k]) {
  251.     printf("Could not allocate string for filename\n");
  252.     exit(1);
  253.       }
  254.         strcpy(files[this_set][k],tmp);
  255.       initfile(tmp,bsize[i]);
  256.         if (i < NBLOCKSIZES-1 && this_set == NSETS-1) k++;
  257.         if (bcount < NBFLUSH_FILES && fcount%44 == 0) {
  258.     sprintf(tmp,"s_%0d",bcount);       /*create spacer file*/
  259.     buf_flush_files[bcount] = malloc(1+strlen(tmp));
  260.     if (!buf_flush_files[bcount]) {
  261.       printf("Could not allocate string for filename\n");
  262.       exit(1);
  263.     }
  264.     strcpy(buf_flush_files[bcount],tmp);
  265.     initfile(tmp,BFLUSH_FILE_SIZE);
  266.     bcount++;
  267.         }
  268.         fcount++;
  269.      }
  270.   }
  271.  
  272.   for(i=0;i<NBFLUSH_FILES;i++) {        /*read spacer files to flush buffers*/
  273.      if ((fd = open(buf_flush_files[i],O_RDWR))<0) /* UNIX 2 */ {
  274.         printf("\nError opening buffer flush file %d of %d.\n",i+1,NBFLUSH_FILES);
  275.       exit(1);
  276.      }
  277.      lseek(fd,0L,0);
  278.     k = BFLUSH_FILE_SIZE/BUFFERSIZE;
  279.      for(j=0;j<k;j++) {
  280.       if((nbytes = read(fd,buffer,BUFFERSIZE))<0) {
  281.     printf("\nError reading buffer flush file %d of %d.\n",j+1,k);
  282.     exit(1);
  283.       }
  284.     }
  285.      close(fd);
  286.   }
  287.  
  288. #ifdef NON_UNIX_TIME
  289.   srand(SEED);
  290. #else
  291.   srandom(SEED);            /*initialize random number generator*/
  292. #endif                    /*and order files in a random*/
  293.   for(i=0;i<NSETS;i++) {        /*permutation for reading/writing*/
  294.      for(j=SET_SIZE;j>0;j--) {
  295.         k=my_rand(j);
  296.         strcpy(tmp,files[i][j-1]);
  297.         strcpy(files[i][j-1],files[i][k]);
  298.         strcpy(files[i][k],tmp);
  299.      }
  300.   }
  301. }
  302.  
  303. long int my_rand(int max)
  304. {
  305. #ifdef NON_UNIX_TIME
  306.   return rand()%max;
  307. #else
  308.   return random()%max;
  309. #endif
  310. }
  311.  
  312.  
  313. void initfile(char *fname,long fsize)
  314. {                                       /*create a temporary file*/
  315.   FILE *fs;
  316.   long int block, num_blocks;
  317.  
  318.   if((fs=fopen(fname,"w"))==NULL){
  319.      printf("init: Cannot create temporary file\n");
  320.      exit(1);
  321.   }
  322.   rewind(fs);                /*write initial portion of file*/
  323.   if (fsize > BUFFERSIZE) {
  324.      num_blocks=fsize/BUFFERSIZE;
  325.      for(block=0;block<num_blocks;block++) {
  326.         if ((nbytes=fwrite(buffer,1,BUFFERSIZE,fs))<0) {
  327.     printf("init: error writing block\n");
  328.     exit(1);
  329.         }
  330.      }
  331.   }
  332.   else {
  333.      if ((nbytes=fwrite(buffer,1,fsize,fs))<0) {
  334.         printf("init: error writing block\n");
  335.         exit(1);
  336.      }
  337.   }
  338.   fclose(fs);
  339. }
  340.  
  341. void readswrites(void){
  342.  
  343.   long int xfer, num_xfer;                   /*to access buffer correct # times*/
  344.   long int xfer_amt;                        /*amount to transfer to/from buffer*/
  345.   long int fsize_index;            /*file size index (0..8)*/
  346.   long int rnum;                /*rand. num to choose read or write*/
  347.   long int rep1,rep2;            /*indices to loop through each file*/
  348.                     /*set twice, and all sets three times*/
  349. #ifdef __OS2__
  350.   HFILE hfFile;
  351.   ULONG ulAction;
  352.   ULONG ulLocal;
  353. #endif
  354.   for(rep1=0;rep1<3;rep1++) {        /*in order to achieve locality which*/
  355.      for(i=0;i<NSETS;i++) {        /*is consistent with buffer cache data*/
  356.         for(rep2=0;rep2<2;rep2++) {    /*of Ousterhout et al (1985)*/
  357. #ifndef NOEXTRAOUTPUT
  358.           printf(".");
  359. #endif
  360.     for(j=0;j<SET_SIZE;j++) {
  361.  
  362. #ifdef __OS2__
  363.           if(DosOpen(files[i][j],
  364.                      &hfFile,
  365.                      &ulAction,
  366.                      0,
  367.                      FILE_NORMAL,
  368.                      FILE_OPEN,
  369.                      OPEN_FLAGS_FAIL_ON_ERROR |
  370.                      OPEN_FLAGS_RANDOMSEQUENTIAL |
  371.                      OPEN_ACCESS_READWRITE |
  372.                      OPEN_SHARE_DENYWRITE,
  373.                      NULL)) /* OS/2 */ {
  374. #else
  375.       if ((fd = open(files[i][j],O_RDWR))<0) /* UNIX 2 */ {
  376. #endif
  377.          printf("readswrites: cannot open file[%d][%d]\n",i,j);
  378.          exit(1);
  379.       }
  380.       fileoc++; /* Counts number of file opens/closes */
  381.       fsize_index = *(files[i][j]) -'0';     /*max xfer_amt = BUFFERSIZE*/
  382.       if (bsize[fsize_index] >= BUFFERSIZE) {
  383.          num_xfer = bsize[fsize_index]/BUFFERSIZE;
  384.          xfer_amt = BUFFERSIZE;}
  385.       else {
  386.          num_xfer = 1;
  387.          xfer_amt = bsize[fsize_index];}
  388.       rnum = my_rand(3);
  389.       if (rnum < 2) {       /*read:write = 2:1*/
  390. #ifdef __OS2__
  391.                  DosSetFilePtr(hfFile,0L,FILE_BEGIN,&ulLocal);
  392. #else
  393.          lseek(fd,0L,0);
  394. #endif
  395.          for (xfer=0; xfer<num_xfer; xfer++) {
  396.             troughr+=xfer_amt; /* Counts total read IO bytes*/
  397. #ifdef __OS2__
  398.                         if(DosRead(hfFile,buffer,xfer_amt,&nbytes)) {
  399. #else
  400.             if((nbytes=read(fd,buffer,xfer_amt))<0) {
  401. #endif
  402.                 printf ("readswrites: read error[%d][%d]\n",i,j);
  403.                 exit(1);
  404.             }
  405.          }
  406.       }
  407.       else {
  408. #ifdef __OS2__
  409.                  DosSetFilePtr(hfFile,0L,FILE_BEGIN,&ulLocal);
  410. #else
  411.          lseek(fd,0L,0);
  412. #endif
  413.          for (xfer=0; xfer<num_xfer; xfer++) {
  414.             troughw+=xfer_amt; /* Counts total write IO bytes*/
  415. #ifdef __OS2__
  416.                         if(DosWrite(hfFile,buffer,xfer_amt,&nbytes)) {
  417. #else
  418.             if((nbytes=write(fd,buffer,xfer_amt))<0) {
  419. #endif
  420.                 printf ("readswrites: write error[%d][%d]\n",i,j);
  421.                 exit(1);
  422.             }
  423.          }
  424.       }
  425. #ifdef __OS2__
  426.           DosClose(hfFile);
  427. #else
  428.       close(fd);
  429. #endif
  430.     }
  431.         }
  432.      }
  433.   }
  434. }
  435.