home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 1 / FishNMoreVol1.bin / more / drive_utils / benchmark / dskprf / diskperf.c < prev    next >
C/C++ Source or Header  |  1987-01-10  |  18KB  |  528 lines

  1. /*
  2. ** Disk performance benchmark.  If your Amiga configuration is substantially
  3. ** different from the ones mentioned here, please run the benchmark and
  4. ** report the results to either: ..!philabs!sbcs!rick or posting to
  5. ** comp.sys.amiga.  Thanks!
  6. **
  7. ** To compile benchmark for Unix 4.2/4.3 SUN 3.0/3.2:
  8. **
  9. **    cc -o diskperf -O -DUNIX diskperf.c
  10. **
  11. ** Amiga version was cross compiled from a SUN, so you'll have to figure out
  12. ** how to compile diskperf under your favorite compiler system.  A uuencoded
  13. ** Amiga binary version of diskperfa is included with the shar file that 
  14. ** contained this source listing.
  15. **
  16. ** To run diskperf, simply type:
  17. **
  18. **    diskperf [location], e.g. (on Amiga) diskperf ram:
  19. **
  20. ** On the Amiga, you will need at least 256K bytes of "disk" wherever you
  21. ** choose to run.  Unix systems will need about 3 mBytes free (larger size
  22. ** test files to delete buffer caching effect).
  23. **
  24. ** Disclaimer:
  25. **
  26. **    This benchmark is provided only for the purpose of seeing how fast
  27. **    _your_ system runs the program.  No claims are made on my part
  28. **    as to what conclusions may be drawn from the statistics gathered.
  29. **    Just consider this program the "Sieve of Eratosthenes" of disk
  30. **    benchmarks - haggle over the numbers with friends, etc, but
  31. **    don't base purchasing decisions solely on the numbers produced
  32. **    by this program.
  33. **
  34. ** Amiga timings gathered thus far:
  35. **
  36. -----------------------------------------------------------------------------
  37. Amiga A-1000, ~7mHz 68000, RAM:
  38.  
  39. File create/delete:    create 5 files/sec, delete 10 files/sec
  40. Directory scan:        5 entries/sec
  41. Seek/read test:        51 seek/reads per second
  42. r/w speed:        buf 512 bytes, rd 201469 byte/sec, wr 154202 byte/sec
  43. r/w speed:        buf 4096 bytes, rd 655360 byte/sec, wr 374491 byte/sec
  44. r/w speed:        buf 8192 bytes, rd 873813 byte/sec, wr 374491 byte/sec
  45. r/w speed:        buf 32768 bytes, rd 873813 byte/sec, wr 436906 byte/sec
  46. -----------------------------------------------------------------------------
  47. Amiga A-1000, ~7mHz 68000, DF1:
  48.  
  49. File create/delete:    create [0..1] files/sec, delete 1 files/sec
  50. Directory scan:        43 entries/sec
  51. Seek/read test:        18 seek/reads per second
  52. r/w speed:        buf 512 bytes, rd 11861 byte/sec, wr 5050 byte/sec
  53. r/w speed:        buf 4096 bytes, rd 12542 byte/sec, wr 5180 byte/sec
  54. r/w speed:        buf 8192 bytes, rd 12542 byte/sec, wr 5130 byte/sec
  55. r/w speed:        buf 32768 bytes, rd 12542 byte/sec, wr 5160 byte/sec
  56. -----------------------------------------------------------------------------
  57. Amiga A-1000/CSA Turbo board, ~14 mHz 68020, no 32 bit ram installed, RAM:
  58.  
  59. File create/delete:    create 7 files/sec, delete 15 files/sec
  60. Directory scan:        8 entries/sec
  61. Seek/read test:        84 seek/reads per second
  62. r/w speed:        buf 512 bytes, rd 187245 byte/sec, wr 145625 byte/sec
  63. r/w speed:        buf 4096 bytes, rd 655360 byte/sec, wr 327680 byte/sec
  64. r/w speed:        buf 8192 bytes, rd 873813 byte/sec, wr 374491 byte/sec
  65. r/w speed:        buf 32768 bytes, rd 873813 byte/sec, wr 436906 byte/sec
  66. -----------------------------------------------------------------------------
  67. Amiga A-1000, ~7 mHz 68000, Ameristar NFS  -> SUN-3/50, Micropolis 1325 disk:
  68.  
  69. File create/delete:    create 3 files/sec, delete 7 files/sec
  70. Directory scan:        10 entries/sec
  71. Seek/read test:        35 seek/reads per second
  72. r/w speed:        buf 512 bytes, rd 30481 byte/sec, wr 3481 byte/sec
  73. r/w speed:        buf 4096 bytes, rd 113975 byte/sec, wr 21664 byte/sec
  74. r/w speed:        buf 8192 bytes, rd 145635 byte/sec, wr 38550 byte/sec
  75. r/w speed:        buf 32768 bytes, rd 145365 byte/sec, wr 37449 byte/sec
  76. -----------------------------------------------------------------------------
  77. SUN-3/50, Adaptec SCSI<->ST-506, Micropolis 1325 drive (5.25", 5 mBit/sec):
  78.  
  79. File create/delete:    create 6 files/sec, delete 11 files/sec
  80. Directory scan:        350 entries/sec
  81. Seek/read test:        298 seek/reads per second
  82. r/w speed:        buf 512 bytes, rd 240499 byte/sec, wr 215166 byte/sec
  83. r/w speed:        buf 4096 bytes, rd 234057 byte/sec, wr 182466 byte/sec
  84. r/w speed:        buf 8192 bytes, rd 233189 byte/sec, wr 179755 byte/sec
  85. r/w speed:        buf 32768 bytes, rd 236343 byte/sec, wr 187580 byte/sec
  86. -----------------------------------------------------------------------------
  87.  
  88. **
  89. ** Some sample figures from "large" systems: 
  90. **
  91.  
  92. -----------------------------------------------------------------------------
  93. SUN-3/160, Fujitsu SuperEagle, Interphase VSMD-3200 controller:
  94.  
  95. File create/delete:    create 15 files/sec, delete 18 files/sec
  96. Directory scan:        722 entries/sec
  97. Seek/read test:        465 seek/reads per second
  98. r/w speed:        buf 512 bytes, rd 361162 byte/sec, wr 307200 byte/sec
  99. r/w speed:        buf 4096 bytes, rd 419430 byte/sec, wr 315519 byte/sec
  100. r/w speed:        buf 8192 bytes, rd 409067 byte/sec, wr 314887 byte/sec
  101. r/w speed:        buf 32768 bytes, rd 409600 byte/sec, wr 328021 byte/sec
  102. -----------------------------------------------------------------------------
  103. SUN-3/75, NFS filesystem, full 8192 byte transactions:
  104.  
  105. File create/delete:    create 9 files/sec, delete 12 files/sec
  106. Directory scan:        88 entries/sec
  107. Seek/read test:        282 seek/reads per second
  108. r/w speed:        buf 512 bytes, rd 238674 byte/sec, wr 52012 byte/sec
  109. r/w speed:        buf 4096 bytes, rd 259334 byte/sec, wr 54956 byte/sec
  110. r/w speed:        buf 8192 bytes, rd 228116 byte/sec, wr 26483 byte/sec
  111. r/w speed:        buf 32768 bytes, rd 243477 byte/sec, wr 36174 byte/sec
  112. -----------------------------------------------------------------------------
  113. DEC VAX 780, RP07:
  114.  
  115. File create/delete:    create 12 files/sec, delete 12 files/sec
  116. Directory scan:        509 entries/sec
  117. Seek/read test:        245 seek/reads per second
  118. r/w speed:        buf 512 bytes, rd 168041 byte/sec, wr 141064 byte/sec
  119. r/w speed:        buf 4096 bytes, rd 210135 byte/sec, wr 239765 byte/sec
  120. r/w speed:        buf 8192 bytes, rd 206277 byte/sec, wr 239948 byte/sec
  121. r/w speed:        buf 32768 bytes, rd 199222 byte/sec, wr 232328 byte/sec
  122. -----------------------------------------------------------------------------
  123. DEC VAX 750, RA81:
  124.  
  125. File create/delete:    create 12 files/sec, delete 15 files/sec
  126. Directory scan:        208 entries/sec
  127. Seek/read test:        153 seek/reads per second
  128. r/w speed:        buf 512 bytes, rd 99864 byte/sec, wr 72549 byte/sec
  129. r/w speed:        buf 4096 bytes, rd 142663 byte/sec, wr 166882 byte/sec
  130. r/w speed:        buf 8192 bytes, rd 147340 byte/sec, wr 153525 byte/sec
  131. r/w speed:        buf 32768 bytes, rd 142340 byte/sec, wr 141571 byte/sec
  132. -----------------------------------------------------------------------------
  133.  
  134. */ 
  135.  
  136. #ifdef UNIX
  137.  
  138. #include <sys/types.h>
  139. #include <sys/file.h>
  140. #include <sys/time.h>
  141. #include <sys/stat.h>
  142.  
  143. #define SCAN_ITER       10
  144. #define RW_ITER         3
  145. #define RW_SIZE         (3*1024*1024)
  146. #define SEEK_TEST_FSIZE (1024*1024)
  147. #define OPEN_TEST_FILES 200
  148. #define TIMER_RATE      100
  149.  
  150. /*
  151. ** Amiga compatibility library for Unix.  These are NOT full or correct 
  152. ** emulations of the Amiga I/F routines - they are intended only to 
  153. ** run this benchmark.
  154. */
  155.  
  156. #define MODE_OLDFILE    1005
  157. #define MODE_NEWFILE    1006
  158. #define ERROR_NO_MORE_ENTRIES 
  159. #define OFFSET_BEGINNING -1
  160. #define OFFSET_CURRENT 0
  161.  
  162. Open(name, accessMode)
  163.         char    *name;
  164.         long    accessMode;
  165. {
  166.         int     flags, file;
  167.  
  168.         flags = O_RDWR;
  169.         if(accessMode == MODE_NEWFILE)
  170.                 flags |= O_TRUNC|O_CREAT;
  171.         if((file = open(name, flags, 0644)) < 0)
  172.                 file = 0;
  173.         return(file);
  174. }
  175.  
  176. /*
  177. ** To be fair, write should be followed by fsync(file) to flush cache.  But
  178. ** since when are benchmarks fair??
  179. */
  180. #define Write(file, buffer, length) write(file, buffer, length)
  181. #define Read(file, buffer, length) read(file, buffer, length)
  182. #define Close(file) close(file)
  183. #define CreateDir(name) mkdir(name, 0755)
  184. #define Seek(file, position, mode) lseek(file, position, \
  185.                 (mode==OFFSET_BEGINNING ? 0 : (mode==OFFSET_CURRENT?1:2)))
  186. #define AllocMem(size, constraints) malloc(size)
  187. #define FreeMem(p, size) free(p, size)
  188. #define DeleteFile(filename) unlink(filename)
  189.  
  190. timer_init()
  191. {
  192.         return(1);
  193. }
  194.  
  195. timer_quit()
  196. {
  197. }
  198.  
  199. timer(valp)
  200.         long    *valp;
  201. {
  202.         static struct timeval ref;
  203.         struct timeval current;
  204.         
  205.         if(valp == (long *)0){
  206.                 gettimeofday(&ref, 0);
  207.                 return;
  208.         } 
  209.         gettimeofday(¤t, 0);
  210.         *valp = (current.tv_usec - ref.tv_usec)/(1000000/TIMER_RATE);
  211.         if(*valp < 0){
  212.                 current.tv_sec--;
  213.                 *valp += TIMER_RATE;
  214.         }
  215.         *valp += (current.tv_sec - ref.tv_sec)*TIMER_RATE;
  216. }
  217.  
  218. OpenStat(filename)
  219.         char    *filename;
  220. {
  221.         int     fd, result;
  222.         struct stat statb;
  223.  
  224.         if((fd = open(filename, 0)) < 0)
  225.                 return(0);
  226.         result = fstat(fd, &statb);
  227.         close(fd);
  228.         return(result == 0);
  229. }
  230.  
  231. #else
  232.  
  233. /*
  234. ** Iteration/size definitions smaller for Amiga so benchmark doesn't take
  235. ** as long and fits on empty floppy.
  236. */
  237.  
  238. #include <exec/types.h>
  239. #include <libraries/dos.h>
  240. #include <devices/timer.h>
  241.  
  242. #ifdef MANX
  243. #include <functions.h>        /* For Manx only */
  244. #endif
  245.  
  246. #define SCAN_ITER       5
  247. #define RW_ITER         3
  248. #define RW_SIZE         (256*1024)
  249. #define SEEK_TEST_FSIZE (256*1024)
  250. #define OPEN_TEST_FILES 100
  251. #define TIMER_RATE      10              /* misnomer, should be resolution */
  252.  
  253. struct MsgPort *timerport, *CreatePort();
  254. struct timerequest *timermsg, *CreateExtIO();
  255. long    TimerBase;
  256.  
  257. timer_init()
  258. {
  259.         timerport = CreatePort(0, 0);
  260.         if(timerport == (struct MsgPort *)0)
  261.                 return(0);
  262.         timermsg = CreateExtIO(timerport, sizeof(struct timerequest));
  263.         if(timermsg == (struct timerequest *)0){
  264.                 DeletePort(timerport);
  265.                 return(0);
  266.         }
  267.         if(OpenDevice(TIMERNAME, UNIT_VBLANK, timermsg, 0) != 0){
  268.                 DeletePort(timerport);
  269.                 DeleteExtIO(timermsg, sizeof(struct timerequest));
  270.                 return(0);
  271.         }
  272.         TimerBase = (long)timermsg->tr_node.io_Device;  /* Hack */
  273.         return(1);
  274. }
  275.  
  276. timer_quit()
  277. {
  278.         CloseDevice(timermsg);
  279.         DeleteExtIO(timermsg, sizeof(struct timerequest));
  280.         DeletePort(timerport);
  281. }
  282.  
  283. timer(valp)
  284.         long    *valp;
  285. {
  286.         static struct timeval ref;
  287.         long    t;
  288.  
  289.         timermsg->tr_node.io_Command = TR_GETSYSTIME;
  290.         DoIO(timermsg);
  291.         t = timermsg->tr_time.tv_secs;
  292.         if(valp == (long *)0)
  293.                 ref = timermsg->tr_time;
  294.         else {
  295.                 SubTime(&timermsg->tr_time, &ref);
  296.                 *valp = timermsg->tr_time.tv_secs*TIMER_RATE +
  297.                         (timermsg->tr_time.tv_micro/(1000000/TIMER_RATE));
  298.         }
  299. }
  300.  
  301. OpenStat(filename)
  302.         char    *filename;
  303. {
  304.         long    lock, result;
  305.         static struct FileInfoBlock fib;  /* must be on &fib mod 4 == 0 */
  306.  
  307.         if((lock = Lock(filename, MODE_OLDFILE)) == 0)
  308.                 return(0); 
  309.         result = Examine(lock, &fib);
  310.         UnLock(lock);
  311.         return(result);
  312. }
  313.  
  314. #endif
  315.  
  316. /*
  317. ** Benchmarks performed:
  318. **
  319. **      1)  Raw file read/write rates.  Tested for operation sizes of
  320. **          512/4096/8192/65536 bytes.  Return read/write figures for each
  321. **          tranfer size in bytes/sec.
  322. **
  323. **      2)  Directory create/delete rates.  Return create/delete entries
  324. **          per second.
  325. **
  326. **      3)  Directory lookup rate.  Create files in directory, and
  327. **          then measure time to lookup, open & stat entire directory contents.
  328. **          Return entries/second.
  329. **
  330. **      4)  Seek speed test - create large file, then seek to various
  331. **          positions in file & read one byte.  Seek distances intentionally
  332. **          chosen large to reduce cacheing effectiveness - want basic
  333. **          speed of disk format here.  Return seeks/second.
  334. */
  335.  
  336. char    *prepend = "";  /* prepend this path to all filenames created   */
  337. char    scratch[8192];  /* scratch buffer used in various tests         */
  338.  
  339. /*
  340. ** Our `C' library for the Amiga is a bit different than Unix's, so this
  341. ** routine will look a bit obtuse to most of you.  Trying to avoid using
  342. ** sprintf()..
  343. */
  344. maketemp(buf, pref)
  345.         char    *buf;
  346. {
  347.         char    *p, *q;
  348.         int     fnum;
  349.         static  int cnt;
  350.         
  351.         fnum = cnt++;
  352.         q = buf;
  353.         if(pref)
  354.                 for(p = prepend; *p; )
  355.                         *q++ = *p++;
  356.         for(p = "diskperf"; *p; )
  357.                 *q++ = *p++;
  358.         *q++ = 'A' + ((fnum>>8)&0xf);
  359.         *q++ = 'A' + ((fnum>>4)&0xf);
  360.         *q++ = 'A' + (fnum&0xf);
  361.         *q++ = 0;
  362. }
  363.  
  364. long    sptest[] = {512, 4096,  8192, 32768, 0};
  365.  
  366. void rw_test()
  367. {
  368.         long    i, j, k, maxsize, file, RDaccTime, WRaccTime, Dt;
  369.         struct timeval t0, t1;
  370.         char    *p, filename[64];
  371.  
  372.         maxsize = -1;
  373.         for(k = 0; sptest[k] != 0; k++)
  374.                 if(sptest[k] > maxsize)
  375.                         maxsize = sptest[k];
  376.         if((p = (char *)AllocMem(maxsize, 0)) == (char *)0){
  377.                 printf("Could not get %d bytes of memory\n", maxsize);
  378.                 return;
  379.         }
  380.         for(k = 0; sptest[k] != 0; k++){
  381.                 RDaccTime = WRaccTime = 0;
  382.                 for(j = 0; j < RW_ITER; j++){
  383.  
  384.                         maketemp(filename, 1);
  385.  
  386.                         if((file = (long) Open(filename, MODE_NEWFILE)) == 0){
  387.                                 printf("Could not create %s\n", filename);
  388.                                 return;
  389.                         }
  390.                         timer(0);
  391.                         for(i = RW_SIZE/sptest[k]; i > 0; i--)
  392.                                 Write(file, p, sptest[k]);
  393.                         timer(&Dt);
  394.                         WRaccTime += Dt;
  395.                         Close(file);
  396.  
  397.                         if((file = (long) Open(filename, MODE_OLDFILE)) == 0){
  398.                                 printf("Could not open %s\n", filename);
  399.                                 return;
  400.                         }
  401.                         timer(0);
  402.                         for(i = RW_SIZE/sptest[k]; i > 0; i--)
  403.                                 Read(file, p, sptest[k]);
  404.                         timer(&Dt);
  405.                         RDaccTime += Dt;
  406.                         Close(file);
  407.  
  408.                         DeleteFile(filename);
  409.                 }
  410.                 printf("r/w speed:\t\tbuf %d bytes, rd %d byte/sec, wr %d byte/sec\n", 
  411.                                 sptest[k],
  412.                                 (TIMER_RATE*RW_SIZE)/(RDaccTime/RW_ITER),
  413.                                 (TIMER_RATE*RW_SIZE)/(WRaccTime/RW_ITER));
  414.  
  415.         }
  416.         FreeMem(p, maxsize);
  417. }
  418.  
  419. seek_test()
  420. {
  421.         char    fname[64];
  422.         long    i, fd, Dt, cnt, pos, dist;
  423.  
  424.         maketemp(fname, 1);
  425.         if((fd = (long) Open(fname, MODE_NEWFILE)) == 0){
  426.                 printf("Could not create %s\n", fname);
  427.                 return;
  428.         }
  429.         for(i = SEEK_TEST_FSIZE/sizeof(scratch); i > 0; i--)
  430.                 if(Write(fd, scratch, sizeof(scratch)) != sizeof(scratch))
  431.                         break;
  432.         if(i == 0){
  433.                 cnt = 0;
  434.                 timer(0);
  435.                 for(dist = 256; dist <= 65536; dist <<= 2)
  436.                         for(pos = 0; pos < SEEK_TEST_FSIZE; pos += dist){
  437.                                 cnt++;
  438.                                 Seek(fd, pos, OFFSET_BEGINNING);
  439.                                 Read(fd, scratch, 1);
  440.                         }
  441.                 timer(&Dt);
  442.                 printf("Seek/read test:\t\t%d seek/reads per second\n", 
  443.                                 (TIMER_RATE*cnt)/Dt);
  444.         }
  445.         Close(fd);
  446.         DeleteFile(fname);
  447. }
  448.  
  449. char    tempname[OPEN_TEST_FILES][16];
  450.  
  451. open_scan_test()
  452. {
  453.         char    dirname[64];
  454.         long    lock, oldlock, cDt, dDt, sDt, i, j, fd, numRead;
  455.         struct FileInfoBlock *fib;
  456.  
  457.         maketemp(dirname, 1);
  458.         lock = CreateDir(dirname);
  459. #ifdef UNIX
  460.         chdir(dirname);
  461. #else
  462.         oldlock = CurrentDir(lock);
  463. #endif
  464.         for(i = 0; i < OPEN_TEST_FILES; i++)
  465.                 maketemp(tempname[i], 0);
  466.         
  467.         /*
  468.         ** Time Open of files.
  469.         */
  470.         timer(0);
  471.         for(i = 0; i < OPEN_TEST_FILES; i++){
  472.                 if((fd = Open(tempname[i], MODE_NEWFILE)) == 0){
  473.                         printf("Could not open %s/%s\n", dirname, tempname);
  474.                         break;
  475.                 }
  476.                 Close(fd);
  477.         }
  478.         timer(&cDt);
  479.  
  480.         /*
  481.         ** Time open scan of directory.
  482.         */
  483.         timer(0);
  484.         numRead = 1;
  485.         for(i = 0; i < SCAN_ITER; i++)
  486.                 for(j = 0; j < OPEN_TEST_FILES; j++)
  487.                         if(OpenStat(tempname[i]) != 0)
  488.                                 numRead++;
  489.         timer(&sDt);
  490.  
  491.         /*
  492.         ** Time Close of files.
  493.         */
  494.         timer(0);
  495.         for(i = 0; i < OPEN_TEST_FILES; i++)
  496.                 DeleteFile(tempname[i]);
  497.         timer(&dDt);
  498.  
  499.         printf("File create/delete:\tcreate %d files/sec, delete %d files/sec\n",
  500.                                 (TIMER_RATE*OPEN_TEST_FILES)/cDt, 
  501.                                 (TIMER_RATE*OPEN_TEST_FILES)/dDt);
  502.         printf("Directory scan:\t\t%d entries/sec\n", 
  503.                                 (TIMER_RATE*numRead)/sDt);
  504. #ifdef UNIX
  505.         chdir("..");
  506.         rmdir(dirname);
  507. #else
  508.         CurrentDir(oldlock);
  509.         DeleteFile(dirname);
  510. #endif
  511. }
  512.  
  513. main(argc, argv)
  514.         int     argc;
  515.         char    **argv;
  516. {
  517.         if(!timer_init()){
  518.                 printf("Could not init timer\n");
  519.                 return(0);      /* Exit in most systems, but not ours! */
  520.         }
  521.         if(argc > 1)
  522.                 prepend = argv[1];
  523.         open_scan_test();
  524.         seek_test();
  525.         rw_test();
  526. }
  527.  
  528.