home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / iostone.zip / IOSTONE.C next >
C/C++ Source or Header  |  1993-07-21  |  10KB  |  331 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.  
  57. #include <stdio.h>
  58. #include <io.h>
  59. #include <string.h>
  60. #include <time.h>
  61. #include <stdlib.h>
  62. #include <sys\stat.h>
  63.  
  64. #define BFLUSH_FILE_SIZE (512L*1024L)   /*size of files used to flush buffers*/
  65. #define NBFLUSH_FILES 8                 /*number of files used to flush buffers*/
  66. #define NBLOCKSIZES 9                   /*number of different block sizes*/
  67. #define SEED 34710373L                  /*random number generator seed*/
  68. #define CONST 500000L                   /*iostone normalization constant*/
  69. #define ITER 4                          /*number of iterations of the code*/
  70. #define BUFFERSIZE (16L*1024L)        /*size of temporary buffer*/
  71.  
  72. /* define only one of the next three defines */
  73. /*#define NOTIME        /* Define if no time function in library */
  74. /*#define TIME            /* Use UNIX time function */
  75. #define NON_UNIX_TIME         /* Use if a non-unix system */
  76.  
  77. #define NSETS 4                         /*number of sets of files*/
  78. #define SET_SIZE 99                     /*number of files in each set*/ 
  79. #define FNAMELEN  8                     /*maximum file name length*/
  80.  
  81. /* char *malloc(); */
  82. char tmp[FNAMELEN];                     /*a temporary string*/
  83. char *files[NSETS][SET_SIZE];           /*array of file names*/
  84. char *buf_flush_files[NBFLUSH_FILES];   /*array of names of files to flush*/
  85.                                                      /*system buffers*/
  86. char buffer[BUFFERSIZE];                /*a temporary buffer*/
  87.  
  88. long int nbytes;                        /*number of bytes transfered*/
  89. int fd;                                 /*file descriptor*/
  90. int i,j,k;                              /*counter variables*/
  91. long bsize[NBLOCKSIZES];                /*array for different block sizes*/
  92. int bfreq[NBLOCKSIZES];                 /*number of accesses for each block*/
  93.  
  94. #ifdef TIME
  95. #include <sys\types.h>
  96. #include <sys\timeb.h>
  97. struct timeb before;
  98. struct timeb after;
  99. int sec;
  100. int msec;
  101. #endif
  102.  
  103. #ifdef NON_UNIX_TIME
  104. long starttime;
  105. long totaltime;
  106. #endif
  107.  
  108. /* PREDEFINISJON */
  109. void init(void);
  110. int my_rand(int max);
  111. void initfile(char *fname,long fsize);
  112. void readswrites(void);
  113.  
  114. void main(void) {
  115.  
  116.   printf("\nIOSTONE is running, please wait a few minutes ...\n\n");
  117.   init();
  118.                                                      /*start timing*/
  119. #ifdef NOTIME
  120.   printf("start timing\n");
  121. #endif
  122. #ifdef TIME
  123.   ftime(&before);
  124. #endif
  125. #ifdef NON_UNIX_TIME
  126.   starttime = time(0);
  127. #endif
  128.  
  129.   for(k=0; k<ITER; k++)            /*perform string of file operations*/
  130.     readswrites();
  131.                     /*stop timimg*/
  132. #ifdef NOTIME
  133.   printf("stop timing\n");
  134. #endif
  135. #ifdef TIME
  136.   ftime(&after);
  137.   sec = after.time - before.time;
  138.   msec = after.millitm - before.millitm;
  139.   if (msec < 0) {            /*adjust if fractional time < 0*/
  140.     sec -= 1;
  141.      msec += 1000;
  142.   }
  143.   printf("Total elapsed time is %d seconds and %d milliseconds\n",sec,msec);
  144.   if (sec!=0 || msec!=0)
  145.      printf("This machine benchmarks at %.0f iostones/second\n",
  146.         ((float)(CONST*ITER)/((float) sec + (float) msec/1000)) + 0.5);
  147. #endif
  148. #ifdef NON_UNIX_TIME
  149.   totaltime = time(0) - starttime;
  150.   printf("Total elapsed time is %ld seconds\n",totaltime);
  151.   if (totaltime!=0)
  152.     printf("This machine benchmarks at %.0f iostones/second\n",
  153.        ((float)(CONST*ITER)/((float) totaltime)) + 0.5);
  154. #endif
  155.   for (i=0;i<NSETS;i++)
  156.     for (j=0;j<SET_SIZE;j++)
  157.         unlink(files[i][j]);              /*remove files*/
  158.   for (k=0;k<NBFLUSH_FILES;k++)
  159.     unlink(buf_flush_files[k]);
  160. }
  161.  
  162. void init(void) {
  163.  
  164.   int this_set;                         /*mark the file set (0..NSETS-1)*/
  165.   int bcount;                           /*counter to track #spacer files*/
  166.   int fcount;                           /*a counter to tell where to create*/
  167.                                         /*files to flush buffer cache and*/
  168.                                         /*spread other files across disk*/ 
  169.   bsize[0]=256; bfreq[0]=128;           
  170.   bsize[1]=512; bfreq[1]=64;   
  171.   bsize[2]=1024; bfreq[2]=64;
  172.   bsize[3]=2048; bfreq[3]=64;
  173.   bsize[4]=4096; bfreq[4]=32;           /*set file block sizes and*/
  174.   bsize[5]=8192; bfreq[5]=32;           /*access frequencies*/
  175.   bsize[6]=16384; bfreq[6]=8;
  176.   bsize[7]=32768; bfreq[7]=2;
  177.   bsize[8]=65536; bfreq[8]=2;
  178.  
  179.   k=0;                                  /*set up files*/
  180.   bcount=0;
  181.   fcount=0;
  182.   for(i=0;i<NBLOCKSIZES;i++) {
  183.     for(j=0;j<bfreq[i];j++) {
  184.       if (i<NBLOCKSIZES-1) 
  185.     this_set = j%NSETS;
  186.       else
  187.     this_set = (j+2)%NSETS;
  188.         sprintf(tmp,"%0d_%0d",i,j);       /*create filename*/
  189.         files[this_set][k] = malloc(1+strlen(tmp));
  190.       if (!files[this_set][k]) {
  191.     printf("Could not allocate string for filename\n");
  192.     exit(1);
  193.       }
  194.         strcpy(files[this_set][k],tmp);
  195.       initfile(tmp,bsize[i]);
  196.         if (i < NBLOCKSIZES-1 && this_set == NSETS-1) k++;
  197.         if (bcount < NBFLUSH_FILES && fcount%44 == 0) {
  198.     sprintf(tmp,"%bf_%0d",bcount);       /*create spacer file*/
  199.     buf_flush_files[bcount] = malloc(1+strlen(tmp));
  200.     if (!buf_flush_files[bcount]) {
  201.       printf("Could not allocate string for filename\n");
  202.       exit(1);
  203.     }
  204.     strcpy(buf_flush_files[bcount],tmp);
  205.     initfile(tmp,BFLUSH_FILE_SIZE);
  206.     bcount++;
  207.         }
  208.         fcount++;
  209.      }
  210.   }      
  211.  
  212.   for(i=0;i<NBFLUSH_FILES;i++) {        /*read spacer files to flush buffers*/
  213.      if ((fd = open(buf_flush_files[i],2))<0) {
  214.         printf("error opening buffer flush file\n");
  215.       exit(1);
  216.      }
  217.      lseek(fd,0L,0);
  218.     k = BFLUSH_FILE_SIZE/BUFFERSIZE;
  219.      for(j=0;j<k;j++) {
  220.       if((nbytes = read(fd,buffer,BUFFERSIZE))<0) {
  221.     printf("Error reading buffer flush file\n");
  222.     exit(1);
  223.       }
  224.     }
  225.     close(fd);
  226.   }
  227.  
  228. #ifdef NON_UNIX_TIME
  229.   srand(SEED);
  230. #else
  231.   srandom(SEED);            /*initialize random number generator*/
  232. #endif                    /*and order files in a random*/
  233.   for(i=0;i<NSETS;i++) {        /*permutation for reading/writing*/
  234.      for(j=SET_SIZE;j>0;j--) {
  235.         k=my_rand(j);
  236.         strcpy(tmp,files[i][j-1]);
  237.         strcpy(files[i][j-1],files[i][k]);
  238.         strcpy(files[i][k],tmp);
  239.      }
  240.   }
  241. }
  242.  
  243. int my_rand(int max)
  244. {
  245. #ifdef NON_UNIX_TIME
  246.   return rand()%max;
  247. #else
  248.   return random()%max;
  249. #endif
  250. }
  251.  
  252.  
  253. void initfile(char *fname,long fsize)
  254. {                                       /*create a temporary file*/
  255.   FILE *fs;
  256.   int block, num_blocks;
  257.  
  258.   if((fs=fopen(fname,"w"))==NULL){
  259.      printf("init: Cannot create temporary file\n");
  260.      exit(1);
  261.   }
  262.   rewind(fs);                /*write initial portion of file*/
  263.   if (fsize > BUFFERSIZE) {
  264.     num_blocks=fsize/BUFFERSIZE;
  265.     for(block=0;block<num_blocks;block++) {
  266.       if ((nbytes=fwrite(buffer,1,BUFFERSIZE,fs))<0) {
  267.     printf("init: error writing block\n");
  268.     exit(1);
  269.         }
  270.      }
  271.   }
  272.   else {
  273.     if ((nbytes=fwrite(buffer,1,fsize,fs))<0) {
  274.       printf("init: error writing block\n");
  275.       exit(1);
  276.     }
  277.   }
  278.   fclose(fs);
  279. }
  280.  
  281. void readswrites(void){
  282.  
  283.   int xfer, num_xfer;                   /*to access buffer correct # times*/
  284.   long xfer_amt;                        /*amount to transfer to/from buffer*/
  285.   int fsize_index;            /*file size index (0..8)*/
  286.   int rnum;                /*rand. num to choose read or write*/
  287.   int rep1,rep2;            /*indices to loop through each file*/
  288.                     /*set twice, and all sets three times*/
  289.   for(rep1=0;rep1<3;rep1++) {        /*in order to achieve locality which*/
  290.      for(i=0;i<NSETS;i++) {        /*is consistent with buffer cache data*/
  291.         for(rep2=0;rep2<2;rep2++) {    /*of Ousterhout et al (1985)*/
  292.     for(j=0;j<SET_SIZE;j++) {
  293.       if ((fd = open(files[i][j],2))<0) {
  294.          printf("readswrites: cannot open file\n");
  295.          exit(1);
  296.       }
  297.       fsize_index = *(files[i][j]) -'0';     /*max xfer_amt = BUFFERSIZE*/
  298.       if (bsize[fsize_index] >= BUFFERSIZE) {
  299.          num_xfer = bsize[fsize_index]/BUFFERSIZE;
  300.          xfer_amt = BUFFERSIZE;}
  301.       else {
  302.         num_xfer = 1;
  303.         xfer_amt = bsize[fsize_index];}
  304.       rnum = my_rand(3);
  305.       if (rnum < 2) {        /*read:write = 2:1*/
  306.         lseek(fd,0L,0);
  307.         for (xfer=0; xfer<num_xfer; xfer++) {
  308.           if((nbytes=read(fd,buffer,xfer_amt))<0) {
  309.         printf ("readswrites: read error\n");
  310.         exit(1);
  311.           }
  312.         }
  313.       }
  314.       else {
  315.         lseek(fd,0L,0);
  316.         for (xfer=0; xfer<num_xfer; xfer++) {
  317.           if((nbytes=write(fd,buffer,xfer_amt))<0) {
  318.         printf ("readswrites: write error\n");
  319.         exit(1);
  320.           }
  321.         }
  322.       }
  323.       close(fd);
  324.     }
  325.       }
  326.     }
  327.   }
  328. }
  329.  
  330.  
  331.