home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / iostone / src / iostone.c next >
Encoding:
C/C++ Source or Header  |  1993-11-20  |  12.3 KB  |  386 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. */
  69.  
  70. #include <stdio.h>
  71. #include <io.h>
  72. #include <string.h>
  73. #include <time.h>
  74. #include <stdlib.h>
  75. #include <sys\stat.h>
  76. #include <fcntl.h>
  77.  
  78. #define BFLUSH_FILE_SIZE (512L*1024L)   /*size of files used to flush buffers*/
  79. #define NBFLUSH_FILES 8                 /*number of files used to flush buffers*/
  80. #define NBLOCKSIZES 9                   /*number of different block sizes*/
  81. #define SEED 34710373L                  /*random number generator seed*/
  82. #define CONST 500000L                   /*iostone normalization constant*/
  83. #define ITER 4                          /*number of iterations of the code*/
  84. #define BUFFERSIZE (16L*1024L)        /*size of temporary buffer*/
  85.  
  86. /* #define NOEXTRAOUTPUT 1    /* Define if you dont want the extra    */
  87.                             /* time consuming output while running. */
  88.  
  89. #define CR=13 /* Carriage Return on MS-DOS system */
  90.  
  91. /* define only one of the next three defines */
  92. /*#define NOTIME        /* Define if no time function in library */
  93. /*#define TIME            /* Use UNIX time function */
  94. #define NON_UNIX_TIME 1        /* Use if a non-unix system */
  95.  
  96. #define NSETS 4                         /*number of sets of files*/
  97. #define SET_SIZE 99                     /*number of files in each set*/
  98. #define FNAMELEN  8                     /*maximum file name length*/
  99.  
  100. /* char *malloc(); */
  101. char tmp[FNAMELEN];                     /*a temporary string*/
  102. char *files[NSETS][SET_SIZE];           /*array of file names*/
  103. char *buf_flush_files[NBFLUSH_FILES];   /*array of names of files to flush*/
  104.                                                      /*system buffers*/
  105. char buffer[BUFFERSIZE];                /*a temporary buffer*/
  106.  
  107. long int nbytes;                        /*number of bytes transfered*/
  108. long int fd;                                 /*file descriptor*/
  109. long int i,j,k;                              /*counter variables*/
  110. long bsize[NBLOCKSIZES];                /*array for different block sizes*/
  111. long bfreq[NBLOCKSIZES];                 /*number of accesses for each block*/
  112.  
  113. #ifdef TIME
  114. #include <sys\types.h>
  115. #include <sys\timeb.h>
  116. struct timeb before;
  117. struct timeb after;
  118. long int sec;
  119. long int msec;
  120. #endif
  121.  
  122. #ifdef NON_UNIX_TIME
  123. long int starttime;
  124. long int totaltime;
  125. #endif
  126.  
  127. /* PREDEFINISJON */
  128. void init(void);
  129. long int my_rand(int max);
  130. void initfile(char *fname,long fsize);
  131. void readswrites(void);
  132.  
  133. unsigned long int troughr; /* Counts number read IO bytes */
  134. unsigned long int troughw; /* Counts number write IO bytes */
  135. unsigned long int fileoc; /* Counts number of file opens/closes */
  136.  
  137. void main(void) {
  138.  
  139.   printf("\nWait - IOSTONE is setting up test files:\t");
  140.   init();
  141.   printf("\rWait - IOSTONE is performing disk IO with varying blocksizes.\t\n");
  142.                             /*start timing*/
  143. #ifdef NOTIME
  144.   printf("start timing\n");
  145. #endif
  146. #ifdef TIME
  147.   ftime(&before);
  148. #endif
  149. #ifdef NON_UNIX_TIME
  150.   starttime = time(0);
  151. #endif
  152.  
  153.   for(k=0; k<ITER; k++)            /*perform string of file operations*/
  154.   {
  155. #ifndef NOEXTRAOUTPUT
  156.     printf("\r\t\t\t\t\t\t\rPass %d:\t",(k+1));
  157. #endif
  158.     readswrites();
  159.   }
  160.                     /*stop timimg*/
  161. #ifdef NOTIME
  162.   printf("stop timing\n");
  163. #endif
  164. #ifdef TIME
  165.   ftime(&after);
  166.   sec = after.time - before.time;
  167.   msec = after.millitm - before.millitm;
  168.   if (msec < 0) {            /*adjust if fractional time < 0*/
  169.     sec -= 1;
  170.      msec += 1000;
  171.   }
  172.   printf("\r\t\t\t\t\t\t\nTotal elapsed time is %d seconds and %d milliseconds.\n",sec,msec);
  173.   printf("Files were opened %u times. %u kb read. %u kb written. \n",
  174.     fileoc,((troughr+512)/1024),((troughw+512)/1024));
  175.   if (sec!=0 || msec!=0)
  176.   {
  177.     printf("Average read/write troughput was %.0f kb/sec, including open/close overhead.\n",
  178.       (((troughr+troughw)/((float) sec + (float) msec/1000)) + 0.5)/1024);
  179.  
  180.      printf("\nThis machine benchmarks at %.0f iostones/sec.\n\n",
  181.         ((float)(CONST*ITER)/((float) sec + (float) msec/1000)) + 0.5);
  182.   }
  183.  
  184. #endif
  185. #ifdef NON_UNIX_TIME
  186.   totaltime = time(0) - starttime;
  187.   printf("\r\t\t\t\t\t\t\nTotal elapsed time is %ld sec.\n",totaltime); /* Uses multipple lines */
  188.   printf("Files were opened %u times.",fileoc);             /* because of bug in BorlandC */
  189.   printf(" %u kb was read, and",((troughr+512)/1024));
  190.   printf(" %u kb written.\n",((troughw+512)/1024));
  191.   if (totaltime!=0)
  192.   {
  193.     printf("Average read/write troughput was %.0f kb/sec, including open/close overhead.\n",
  194.       (((troughr+troughw)/((float) totaltime)) + 0.5)/1024);
  195.  
  196.     printf("\nThis machine benchmarks at %.0f iostones/sec.\n\n",
  197.         ((float)(CONST*ITER)/((float) totaltime)) + 0.5);
  198.   }
  199.  
  200. #endif
  201.   for (i=0;i<NSETS;i++)
  202.     for (j=0;j<SET_SIZE;j++)
  203.         unlink(files[i][j]);              /*remove files*/
  204.   for (k=0;k<NBFLUSH_FILES;k++)
  205.     unlink(buf_flush_files[k]);
  206. }
  207.  
  208. void init(void) {
  209.  
  210.   long int this_set;                         /*mark the file set (0..NSETS-1)*/
  211.   long int bcount;                           /*counter to track #spacer files*/
  212.   long int fcount;                           /*a counter to tell where to create*/
  213.                                         /*files to flush buffer cache and*/
  214.                                         /*spread other files across disk*/
  215.   bsize[0]=256; bfreq[0]=128;
  216.   bsize[1]=512; bfreq[1]=64;
  217.   bsize[2]=1024; bfreq[2]=64;
  218.   bsize[3]=2048; bfreq[3]=64;
  219.   bsize[4]=4096; bfreq[4]=32;           /*set file block sizes and*/
  220.   bsize[5]=8192; bfreq[5]=32;           /*access frequencies*/
  221.   bsize[6]=16384; bfreq[6]=8;
  222.   bsize[7]=32768; bfreq[7]=2;
  223.   bsize[8]=65536; bfreq[8]=2;
  224.  
  225.   troughr=0;
  226.   troughw=0;
  227.   fileoc=0;
  228.  
  229.   k=0;                                  /*set up files*/
  230.   bcount=0;
  231.   fcount=0;
  232.   for(i=0;i<NBLOCKSIZES;i++) {
  233.     printf(".");
  234.     for(j=0;j<bfreq[i];j++) {
  235.       if (i<NBLOCKSIZES-1)
  236.     this_set = j%NSETS;
  237.       else
  238.     this_set = (j+2)%NSETS;
  239.         sprintf(tmp,"%0d_%0d",i,j);       /*create filename*/
  240.         files[this_set][k] = malloc(1+strlen(tmp));
  241.       if (!files[this_set][k]) {
  242.     printf("Could not allocate string for filename\n");
  243.     exit(1);
  244.       }
  245.         strcpy(files[this_set][k],tmp);
  246.       initfile(tmp,bsize[i]);
  247.         if (i < NBLOCKSIZES-1 && this_set == NSETS-1) k++;
  248.         if (bcount < NBFLUSH_FILES && fcount%44 == 0) {
  249.     sprintf(tmp,"s_%0d",bcount);       /*create spacer file*/
  250.     buf_flush_files[bcount] = malloc(1+strlen(tmp));
  251.     if (!buf_flush_files[bcount]) {
  252.       printf("Could not allocate string for filename\n");
  253.       exit(1);
  254.     }
  255.     strcpy(buf_flush_files[bcount],tmp);
  256.     initfile(tmp,BFLUSH_FILE_SIZE);
  257.     bcount++;
  258.         }
  259.         fcount++;
  260.      }
  261.   }
  262.  
  263.   for(i=0;i<NBFLUSH_FILES;i++) {        /*read spacer files to flush buffers*/
  264.      if ((fd = open(buf_flush_files[i],O_RDWR))<0) /* UNIX 2 */ {
  265.         printf("\nError opening buffer flush file %d of %d.\n",i+1,NBFLUSH_FILES);
  266.       exit(1);
  267.      }
  268.      lseek(fd,0L,0);
  269.     k = BFLUSH_FILE_SIZE/BUFFERSIZE;
  270.      for(j=0;j<k;j++) {
  271.       if((nbytes = read(fd,buffer,BUFFERSIZE))<0) {
  272.     printf("\nError reading buffer flush file %d of %d.\n",j+1,k);
  273.     exit(1);
  274.       }
  275.     }
  276.      close(fd);
  277.   }
  278.  
  279. #ifdef NON_UNIX_TIME
  280.   srand(SEED);
  281. #else
  282.   srandom(SEED);            /*initialize random number generator*/
  283. #endif                    /*and order files in a random*/
  284.   for(i=0;i<NSETS;i++) {        /*permutation for reading/writing*/
  285.      for(j=SET_SIZE;j>0;j--) {
  286.         k=my_rand(j);
  287.         strcpy(tmp,files[i][j-1]);
  288.         strcpy(files[i][j-1],files[i][k]);
  289.         strcpy(files[i][k],tmp);
  290.      }
  291.   }
  292. }
  293.  
  294. long int my_rand(int max)
  295. {
  296. #ifdef NON_UNIX_TIME
  297.   return rand()%max;
  298. #else
  299.   return random()%max;
  300. #endif
  301. }
  302.  
  303.  
  304. void initfile(char *fname,long fsize)
  305. {                                       /*create a temporary file*/
  306.   FILE *fs;
  307.   long int block, num_blocks;
  308.  
  309.   if((fs=fopen(fname,"w"))==NULL){
  310.      printf("init: Cannot create temporary file\n");
  311.      exit(1);
  312.   }
  313.   rewind(fs);                /*write initial portion of file*/
  314.   if (fsize > BUFFERSIZE) {
  315.      num_blocks=fsize/BUFFERSIZE;
  316.      for(block=0;block<num_blocks;block++) {
  317.         if ((nbytes=fwrite(buffer,1,BUFFERSIZE,fs))<0) {
  318.     printf("init: error writing block\n");
  319.     exit(1);
  320.         }
  321.      }
  322.   }
  323.   else {
  324.      if ((nbytes=fwrite(buffer,1,fsize,fs))<0) {
  325.         printf("init: error writing block\n");
  326.         exit(1);
  327.      }
  328.   }
  329.   fclose(fs);
  330. }
  331.  
  332. void readswrites(void){
  333.  
  334.   long int xfer, num_xfer;                   /*to access buffer correct # times*/
  335.   long int xfer_amt;                        /*amount to transfer to/from buffer*/
  336.   long int fsize_index;            /*file size index (0..8)*/
  337.   long int rnum;                /*rand. num to choose read or write*/
  338.   long int rep1,rep2;            /*indices to loop through each file*/
  339.                     /*set twice, and all sets three times*/
  340.   for(rep1=0;rep1<3;rep1++) {        /*in order to achieve locality which*/
  341.      for(i=0;i<NSETS;i++) {        /*is consistent with buffer cache data*/
  342.         for(rep2=0;rep2<2;rep2++) {    /*of Ousterhout et al (1985)*/
  343. #ifndef NOEXTRAOUTPUT
  344.           printf(".");
  345. #endif
  346.     for(j=0;j<SET_SIZE;j++) {
  347.       if ((fd = open(files[i][j],O_RDWR))<0) /* UNIX 2 */ {
  348.          printf("readswrites: cannot open file[%d][%d]\n",i,j);
  349.          exit(1);
  350.       }
  351.       fileoc++; /* Counts number of file opens/closes */
  352.       fsize_index = *(files[i][j]) -'0';     /*max xfer_amt = BUFFERSIZE*/
  353.       if (bsize[fsize_index] >= BUFFERSIZE) {
  354.          num_xfer = bsize[fsize_index]/BUFFERSIZE;
  355.          xfer_amt = BUFFERSIZE;}
  356.       else {
  357.          num_xfer = 1;
  358.          xfer_amt = bsize[fsize_index];}
  359.       rnum = my_rand(3);
  360.       if (rnum < 2) {        /*read:write = 2:1*/
  361.          lseek(fd,0L,0);
  362.          for (xfer=0; xfer<num_xfer; xfer++) {
  363.             troughr+=xfer_amt; /* Counts total read IO bytes*/
  364.             if((nbytes=read(fd,buffer,xfer_amt))<0) {
  365.                 printf ("readswrites: read error[%d][%d]\n",i,j);
  366.                 exit(1);
  367.             }
  368.          }
  369.       }
  370.       else {
  371.          lseek(fd,0L,0);
  372.          for (xfer=0; xfer<num_xfer; xfer++) {
  373.             troughw+=xfer_amt; /* Counts total write IO bytes*/
  374.             if((nbytes=write(fd,buffer,xfer_amt))<0) {
  375.                 printf ("readswrites: write error[%d][%d]\n",i,j);
  376.                 exit(1);
  377.             }
  378.          }
  379.       }
  380.       close(fd);
  381.     }
  382.         }
  383.      }
  384.   }
  385. }
  386.