home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Disk performance benchmark. If your Amiga configuration is substantially
- ** different from the ones mentioned here, please run the benchmark and
- ** report the results to either: ..!philabs!sbcs!rick or posting to
- ** comp.sys.amiga. Thanks!
- **
- ** To compile benchmark for Unix 4.2/4.3 SUN 3.0/3.2:
- **
- ** cc -o diskperf -O -DUNIX diskperf.c
- **
- ** Amiga version was cross compiled from a SUN, so you'll have to figure out
- ** how to compile diskperf under your favorite compiler system. A uuencoded
- ** Amiga binary version of diskperfa is included with the shar file that
- ** contained this source listing.
- **
- ** To run diskperf, simply type:
- **
- ** diskperf [location], e.g. (on Amiga) diskperf ram:
- **
- ** On the Amiga, you will need at least 256K bytes of "disk" wherever you
- ** choose to run. Unix systems will need about 3 mBytes free (larger size
- ** test files to delete buffer caching effect).
- **
- ** Disclaimer:
- **
- ** This benchmark is provided only for the purpose of seeing how fast
- ** _your_ system runs the program. No claims are made on my part
- ** as to what conclusions may be drawn from the statistics gathered.
- ** Just consider this program the "Sieve of Eratosthenes" of disk
- ** benchmarks - haggle over the numbers with friends, etc, but
- ** don't base purchasing decisions solely on the numbers produced
- ** by this program.
- **
- ** Addendum:
- ** Timings may also be reported in BIX where Rick is rspanbauer. This has
- ** been slightly modified by jdow@bix. It no longer leaves dangling locks.
- ** It now executes reads as large as 524288 bytes. It also makes more reads
- ** so that hard disk timings are more accurate. As such it may be a bit
- ** difficult to run on smaller Amigas or particularly slow disk drives.
- ** It also now compiles under Lattice C. (At least 4.1.)
- ** lc:lc -dLATTICE -b0 -Lm -r0 diskperf ==> This works even if not optimal.
- **
- ** Timings:
- ** Various timings gathered thus far:
- **
- -----------------------------------------------------------------------------
- Amiga A-2000/A2620 ~14mHZ 68020, Micropolis 1578 HardDisk with MicroBotics
- HardFrame controller.
-
- File create/delete: create 20 files/sec, delete 55 files/sec
- Directory scan: 227 entries/sec
- Seek/read test: 317 seek/reads per second
- r/w speed: buf 512 bytes, rd 123604 byte/sec, wr 28519 byte/sec
- r/w speed: buf 4096 bytes, rd 194781 byte/sec, wr 163840 byte/sec
- r/w speed: buf 8192 bytes, rd 32939= byte/sec, wr 247695 byte/sec
- r/w speed: buf 32768 bytes, rd 683853 byte/sec, wr 367921 byte/sec
- r/w speed: buf 131072 bytes, rd 925214 byte/sec, wr 483958 byte/sec
- r/w speed: buf 524288 bytes, rd 953250 byte/sec, wr 537731 byte/sec
- -----------------------------------------------------------------------------
- Amiga A-1000, ~7mHz 68000, RAM:
-
- File create/delete: create 5 files/sec, delete 10 files/sec
- Directory scan: 5 entries/sec
- Seek/read test: 51 seek/reads per second
- r/w speed: buf 512 bytes, rd 201469 byte/sec, wr 154202 byte/sec
- r/w speed: buf 4096 bytes, rd 655360 byte/sec, wr 374491 byte/sec
- r/w speed: buf 8192 bytes, rd 873813 byte/sec, wr 374491 byte/sec
- r/w speed: buf 32768 bytes, rd 873813 byte/sec, wr 436906 byte/sec
- -----------------------------------------------------------------------------
- Amiga A-1000, ~7mHz 68000, DF1:
-
- File create/delete: create [0..1] files/sec, delete 1 files/sec
- Directory scan: 43 entries/sec
- Seek/read test: 18 seek/reads per second
- r/w speed: buf 512 bytes, rd 11861 byte/sec, wr 5050 byte/sec
- r/w speed: buf 4096 bytes, rd 12542 byte/sec, wr 5180 byte/sec
- r/w speed: buf 8192 bytes, rd 12542 byte/sec, wr 5130 byte/sec
- r/w speed: buf 32768 bytes, rd 12542 byte/sec, wr 5160 byte/sec
- -----------------------------------------------------------------------------
- Amiga A-1000/CSA Turbo board, ~14 mHz 68020, no 32 bit ram installed, RAM:
-
- File create/delete: create 7 files/sec, delete 15 files/sec
- Directory scan: 8 entries/sec
- Seek/read test: 84 seek/reads per second
- r/w speed: buf 512 bytes, rd 187245 byte/sec, wr 145625 byte/sec
- r/w speed: buf 4096 bytes, rd 655360 byte/sec, wr 327680 byte/sec
- r/w speed: buf 8192 bytes, rd 873813 byte/sec, wr 374491 byte/sec
- r/w speed: buf 32768 bytes, rd 873813 byte/sec, wr 436906 byte/sec
- -----------------------------------------------------------------------------
- Amiga A-1000, ~7 mHz 68000, Ameristar NFS -> SUN-3/50, Micropolis 1325 disk:
-
- File create/delete: create 3 files/sec, delete 7 files/sec
- Directory scan: 10 entries/sec
- Seek/read test: 35 seek/reads per second
- r/w speed: buf 512 bytes, rd 30481 byte/sec, wr 3481 byte/sec
- r/w speed: buf 4096 bytes, rd 113975 byte/sec, wr 21664 byte/sec
- r/w speed: buf 8192 bytes, rd 145635 byte/sec, wr 38550 byte/sec
- r/w speed: buf 32768 bytes, rd 145365 byte/sec, wr 37449 byte/sec
- -----------------------------------------------------------------------------
- SUN-3/50, Adaptec SCSI<->ST-506, Micropolis 1325 drive (5.25", 5 mBit/sec):
-
- File create/delete: create 6 files/sec, delete 11 files/sec
- Directory scan: 350 entries/sec
- Seek/read test: 298 seek/reads per second
- r/w speed: buf 512 bytes, rd 240499 byte/sec, wr 215166 byte/sec
- r/w speed: buf 4096 bytes, rd 234057 byte/sec, wr 182466 byte/sec
- r/w speed: buf 8192 bytes, rd 233189 byte/sec, wr 179755 byte/sec
- r/w speed: buf 32768 bytes, rd 236343 byte/sec, wr 187580 byte/sec
- -----------------------------------------------------------------------------
-
- **
- ** Some sample figures from "large" systems:
- **
-
- -----------------------------------------------------------------------------
- SUN-3/160, Fujitsu SuperEagle, Interphase VSMD-3200 controller:
-
- File create/delete: create 15 files/sec, delete 18 files/sec
- Directory scan: 722 entries/sec
- Seek/read test: 465 seek/reads per second
- r/w speed: buf 512 bytes, rd 361162 byte/sec, wr 307200 byte/sec
- r/w speed: buf 4096 bytes, rd 419430 byte/sec, wr 315519 byte/sec
- r/w speed: buf 8192 bytes, rd 409067 byte/sec, wr 314887 byte/sec
- r/w speed: buf 32768 bytes, rd 409600 byte/sec, wr 328021 byte/sec
- -----------------------------------------------------------------------------
- SUN-3/75, NFS filesystem, full 8192 byte transactions:
-
- File create/delete: create 9 files/sec, delete 12 files/sec
- Directory scan: 88 entries/sec
- Seek/read test: 282 seek/reads per second
- r/w speed: buf 512 bytes, rd 238674 byte/sec, wr 52012 byte/sec
- r/w speed: buf 4096 bytes, rd 259334 byte/sec, wr 54956 byte/sec
- r/w speed: buf 8192 bytes, rd 228116 byte/sec, wr 26483 byte/sec
- r/w speed: buf 32768 bytes, rd 243477 byte/sec, wr 36174 byte/sec
- -----------------------------------------------------------------------------
- DEC VAX 780, RP07:
-
- File create/delete: create 12 files/sec, delete 12 files/sec
- Directory scan: 509 entries/sec
- Seek/read test: 245 seek/reads per second
- r/w speed: buf 512 bytes, rd 168041 byte/sec, wr 141064 byte/sec
- r/w speed: buf 4096 bytes, rd 210135 byte/sec, wr 239765 byte/sec
- r/w speed: buf 8192 bytes, rd 206277 byte/sec, wr 239948 byte/sec
- r/w speed: buf 32768 bytes, rd 199222 byte/sec, wr 232328 byte/sec
- -----------------------------------------------------------------------------
- DEC VAX 750, RA81:
-
- File create/delete: create 12 files/sec, delete 15 files/sec
- Directory scan: 208 entries/sec
- Seek/read test: 153 seek/reads per second
- r/w speed: buf 512 bytes, rd 99864 byte/sec, wr 72549 byte/sec
- r/w speed: buf 4096 bytes, rd 142663 byte/sec, wr 166882 byte/sec
- r/w speed: buf 8192 bytes, rd 147340 byte/sec, wr 153525 byte/sec
- r/w speed: buf 32768 bytes, rd 142340 byte/sec, wr 141571 byte/sec
- -----------------------------------------------------------------------------
-
- */
-
- #ifdef UNIX
-
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/time.h>
- #include <sys/stat.h>
-
- #define SCAN_ITER 10
- #define RW_ITER 3
- #define RW_SIZE (3*1024*1024)
- #define SEEK_TEST_FSIZE (1024*1024)
- #define OPEN_TEST_FILES 200
- #define TIMER_RATE 100
-
- /*
- ** Amiga compatibility library for Unix. These are NOT full or correct
- ** emulations of the Amiga I/F routines - they are intended only to
- ** run this benchmark.
- */
-
- #define MODE_OLDFILE 1005
- #define MODE_NEWFILE 1006
- #define ERROR_NO_MORE_ENTRIES
- #define OFFSET_BEGINNING -1
- #define OFFSET_CURRENT 0
-
- int
- Open(name, accessMode)
- char *name;
- long accessMode;
- {
- int flags, file;
-
- flags = O_RDWR;
- if(accessMode == MODE_NEWFILE)
- flags |= O_TRUNC|O_CREAT;
- if((file = open(name, flags, 0644)) < 0)
- file = 0;
- return(file);
- }
-
- /*
- ** To be fair, write should be followed by fsync(file) to flush cache. But
- ** since when are benchmarks fair??
- */
- #define Write(file, buffer, length) write(file, buffer, length)
- #define Read(file, buffer, length) read(file, buffer, length)
- #define Close(file) close(file)
- #define CreateDir(name) mkdir(name, 0755)
- #define Seek(file, position, mode) lseek(file, position, \
- (mode==OFFSET_BEGINNING ? 0 : (mode==OFFSET_CURRENT?1:2)))
- #define AllocMem(size, constraints) malloc(size)
- #define FreeMem(p, size) free(p, size)
- #define DeleteFile(filename) unlink(filename)
-
- int
- timer_init()
- {
- return(1);
- }
-
- void
- timer_quit()
- {
- }
-
- void
- timer(valp)
- long *valp;
- {
- static struct timeval ref;
- struct timeval current;
-
- if(valp == (long *)0){
- gettimeofday(&ref, 0);
- return;
- }
- gettimeofday(¤t, 0);
- *valp = (current.tv_usec - ref.tv_usec)/(1000000/TIMER_RATE);
- if(*valp < 0){
- current.tv_sec--;
- *valp += TIMER_RATE;
- }
- *valp += (current.tv_sec - ref.tv_sec)*TIMER_RATE;
- }
-
- int
- OpenStat(filename)
- char *filename;
- {
- int fd, result;
- struct stat statb;
-
- if((fd = open(filename, 0)) < 0)
- return(0);
- result = fstat(fd, &statb);
- close(fd);
- return(result == 0);
- }
-
- #else
-
- /*
- ** Iteration/size definitions smaller for Amiga so benchmark doesn't take
- ** as long and fits on empty floppy.
- */
-
- #include <exec/types.h>
- #include <libraries/dos.h>
- #include <devices/timer.h>
-
- #ifdef MANX
- #include <functions.h> /* For Manx only */
- #endif
-
- #define SCAN_ITER 5
- #define RW_ITER 3
- #define RW_SIZE (2*1024*1024)
- #define SEEK_TEST_FSIZE (256*1024)
- #define OPEN_TEST_FILES 100
- #define TIMER_RATE 10 /* misnomer, should be resolution */
-
- struct MsgPort *timerport, *CreatePort();
- struct timerequest *timermsg, *CreateExtIO();
- long TimerBase;
-
- int
- timer_init()
- {
- timerport = CreatePort(0, 0);
- if(timerport == (struct MsgPort *)0)
- return(0);
- timermsg = CreateExtIO(timerport, sizeof(struct timerequest));
- if(timermsg == (struct timerequest *)0){
- DeletePort(timerport);
- return(0);
- }
- if(OpenDevice(TIMERNAME, UNIT_VBLANK, timermsg, 0) != 0){
- DeletePort(timerport);
- DeleteExtIO(timermsg, sizeof(struct timerequest));
- return(0);
- }
- TimerBase = (long)timermsg->tr_node.io_Device; /* Hack */
- return(1);
- }
-
- void
- timer_quit()
- {
- CloseDevice(timermsg);
- DeleteExtIO(timermsg, sizeof(struct timerequest));
- DeletePort(timerport);
- }
-
- void
- timer(valp)
- long *valp;
- {
- static struct timeval ref;
- long t;
-
- timermsg->tr_node.io_Command = TR_GETSYSTIME;
- DoIO(timermsg);
- t = timermsg->tr_time.tv_secs;
- if(valp == (long *)0)
- ref = timermsg->tr_time;
- else {
- SubTime(&timermsg->tr_time, &ref);
- *valp = timermsg->tr_time.tv_secs*TIMER_RATE +
- (timermsg->tr_time.tv_micro/(1000000/TIMER_RATE));
- }
- }
-
- int
- OpenStat(filename)
- char *filename;
- {
- long lock, result;
- static struct FileInfoBlock fib; /* must be on &fib mod 4 == 0 */
-
- if((lock = Lock(filename, MODE_OLDFILE)) == 0)
- return(0);
- result = Examine(lock, &fib);
- UnLock(lock);
- return(result);
- }
-
- #endif
-
- /*
- ** Benchmarks performed:
- **
- ** 1) Raw file read/write rates. Tested for operation sizes of
- ** 512/4096/8192/32768/131072/524288 bytes. Return read/write figures
- ** for each tranfer size in bytes/sec.
- **
- ** 2) Directory create/delete rates. Return create/delete entries
- ** per second.
- **
- ** 3) Directory lookup rate. Create files in directory, and
- ** then measure time to lookup, open & stat entire directory contents.
- ** Return entries/second.
- **
- ** 4) Seek speed test - create large file, then seek to various
- ** positions in file & read one byte. Seek distances intentionally
- ** chosen large to reduce cacheing effectiveness - want basic
- ** speed of disk format here. Return seeks/second.
- */
-
- char *prepend = ""; /* prepend this path to all filenames created */
- char scratch[8192]; /* scratch buffer used in various tests */
-
- /*
- ** Our `C' library for the Amiga is a bit different than Unix's, so this
- ** routine will look a bit obtuse to most of you. Trying to avoid using
- ** sprintf()..
- */
- void
- maketemp(buf, pref)
- char *buf;
- {
- char *p, *q;
- int fnum;
- static int cnt;
-
- fnum = cnt++;
- q = buf;
- if(pref)
- for(p = prepend; *p; )
- *q++ = *p++;
- for(p = "diskperf"; *p; )
- *q++ = *p++;
- *q++ = 'A' + ((fnum>>8)&0xf);
- *q++ = 'A' + ((fnum>>4)&0xf);
- *q++ = 'A' + (fnum&0xf);
- *q++ = 0;
- }
-
- long sptest[] = {512, 4096, 8192, 32768, 131072, 524288, 0};
-
- void rw_test()
- {
- long i, j, k, maxsize, file, RDaccTime, WRaccTime, Dt, error;
- char *p, filename[64];
-
- maxsize = -1;
- for(k = 0; sptest[k] != 0; k++)
- if(sptest[k] > maxsize)
- maxsize = sptest[k];
- if((p = (char *)AllocMem(maxsize, 0)) == (char *)0L){
- printf("Could not get %d bytes of memory\n", maxsize);
- return;
- }
- for(k = 0; sptest[k] != (char *) 0L; k++){
- RDaccTime = WRaccTime = 0;
- for(j = 0; j < RW_ITER; j++){
-
- maketemp(filename, 1);
-
- if((file = (long) Open(filename, MODE_NEWFILE)) == 0){
- printf("Could not create %s\n", filename);
- return;
- }
- timer(0);
- for(i = RW_SIZE/sptest[k]; i > 0; i--)
- error = Write(file, p, sptest[k]);
- timer(&Dt);
- if (error != sptest[k])
- printf("Write error! %d != %d\n", sptest[k], error);
- WRaccTime += Dt;
- Close(file);
-
- if((file = (long) Open(filename, MODE_OLDFILE)) == 0){
- printf("Could not open %s\n", filename);
- return;
- }
- timer(0);
- for(i = RW_SIZE/sptest[k]; i > 0; i--)
- error = Read(file, p, sptest[k]);
- timer(&Dt);
- if (error != sptest[k])
- printf("Read error! %d != %d\n", sptest[k], error);
- RDaccTime += Dt;
- Close(file);
-
- DeleteFile(filename);
- }
- if (RDaccTime == 0) printf( "Still bingo read.\n");
- else printf("r/w speed:\t buf %d bytes, rd %d byte/sec, wr %d byte/sec\n",
- sptest[k],
- (TIMER_RATE*RW_SIZE*RW_ITER)/RDaccTime,
- (TIMER_RATE*RW_SIZE*RW_ITER)/WRaccTime);
-
- }
- FreeMem(p, maxsize);
- }
-
- void
- seek_test()
- {
- char fname[64];
- long i, fd, Dt, cnt, pos, dist;
-
- maketemp(fname, 1);
- if((fd = (long) Open(fname, MODE_NEWFILE)) == 0){
- printf("Could not create %s\n", fname);
- return;
- }
- for(i = SEEK_TEST_FSIZE/sizeof(scratch); i > 0; i--)
- if(Write(fd, scratch, sizeof(scratch)) != sizeof(scratch))
- break;
- if(i == 0){
- cnt = 0;
- timer(0);
- for(dist = 256; dist <= 65536; dist <<= 2)
- for(pos = 0; pos < SEEK_TEST_FSIZE; pos += dist){
- cnt++;
- Seek(fd, pos, OFFSET_BEGINNING);
- Read(fd, scratch, 1);
- }
- timer(&Dt);
- printf("Seek/read test:\t %d seek/reads per second\n",
- (TIMER_RATE*cnt)/Dt);
- }
- Close(fd);
- DeleteFile(fname);
- }
-
- char tempname[OPEN_TEST_FILES][16];
-
- void
- open_scan_test()
- {
- char dirname[64];
- long lock, oldlock, cDt, dDt, sDt, i, j, fd, numRead;
- /* struct FileInfoBlock *fib; */
-
- maketemp(dirname, 1);
- lock = CreateDir(dirname);
- #ifdef UNIX
- chdir(dirname);
- #else
- oldlock = CurrentDir(lock);
- #endif
- for(i = 0; i < OPEN_TEST_FILES; i++)
- maketemp(tempname[i], 0);
-
- /*
- ** Time Open of files.
- */
- timer(0);
- for(i = 0; i < OPEN_TEST_FILES; i++){
- if((fd = Open(tempname[i], MODE_NEWFILE)) == 0){
- printf("Could not open %s/%s\n", dirname, tempname);
- break;
- }
- Close(fd);
- }
- timer(&cDt);
-
- /*
- ** Time open scan of directory.
- */
- timer(0);
- numRead = 1;
- for(i = 0; i < SCAN_ITER; i++)
- for(j = 0; j < OPEN_TEST_FILES; j++)
- if(OpenStat(tempname[i]) != 0)
- numRead++;
- timer(&sDt);
-
- /*
- ** Time Close of files.
- */
- timer(0);
- for(i = 0; i < OPEN_TEST_FILES; i++)
- DeleteFile(tempname[i]);
- timer(&dDt);
-
- printf("File create/delete: create %d files/sec, delete %d files/sec\n",
- (TIMER_RATE*OPEN_TEST_FILES)/cDt,
- (TIMER_RATE*OPEN_TEST_FILES)/dDt);
- printf("Directory scan:\t %d entries/sec\n",
- (TIMER_RATE*numRead)/sDt);
- #ifdef UNIX
- chdir("..");
- rmdir(dirname);
- #else
- CurrentDir(oldlock);
- UnLock(lock);
- DeleteFile(dirname);
- #endif
- }
-
- void
- main(argc, argv)
- int argc;
- char **argv;
- {
- if(!timer_init()){
- printf("Could not init timer\n");
- return(0); /* Exit in most systems, but not ours! */
- }
- if(argc > 1)
- prepend = argv[1];
- open_scan_test();
- seek_test();
- rw_test();
- }
-
-