Path: utzoo!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!agate!bionet!apple!rutgers!mailrus!ncar!noao!asuvax!nud!fishpond!fnf From: fnf@fishpond.UUCP (Fred Fish) Newsgroups: comp.unix.aux Subject: Re: Some questions about A/UX Message-ID: <165@fishpond.UUCP> Date: 25 Nov 88 16:56:38 GMT References: <941@ccnysci.UUCP> <19528@apple.Apple.COM> <964@ccnysci.UUCP> <19816@apple.Apple.COM> <1011@ccnysci.UUCP> <21057@apple.Apple.COM> <16775@onfcanim.UUCP> Reply-To: fnf@fishpond.UUCP (Fred Fish) Organization: occasionally Lines: 602 In article <16775@onfcanim.UUCP> dave@onfcanim.UUCP (Dave Martindale) writes: >The Silicon Graphics IRIS 3000 series uses a 16 MHz 68020, with memory >management. The old 70 Mb disks use an ST506 interface - SCSI should >do better. The kernel is basically system V release something, and they >get several times the disk throughput of A/UX. > >Why? Basically because they don't use the system V filesystem - they >replaced it with an extent-based filesystem that reads and writes >much larger data blocks at a time. I believe that the only way A/UX >will get decent performance out of the disk is by switching to a >different filesystem. Maybe it's just a rumor, but I once heard from someone close to the A/UX project that the BSD filesystem was tried with A/UX, and it turned out to be even slower than the System V filesystem on the Mac-II hardware. There was an explanation, but I confess I didn't listen too closely to it. I hope that this is wrong, and that we will someday see a BSD filesystem with A/UX, because there are lots of things about A/UX that I like. I decided to retry the disk performance benchmark that I ran in Feb '88 and posted the results for. This posting contains a copy of that benchmark at the end. Here are the current results for an Amiga 2000 and the Mac-II, along with some old results for a Sun-3/50. Performance timings using Rick Spanbauer's diskperf.c program. Amiga Sun A/UX A/UX 2000 3/50 Mac-II Mac-II ST277N HD80SC HD80SC Nov 88 ????? Feb 88 Nov 88 File creations (files/sec) 14 6 6 6 File deletions (files/sec) 41 11 8 8 Directory scan (entries/sec) 92 350 371 397 Seek+read (seek+read/sec) 85 298 110 93 Read speed, 512 buffer (byte/sec) 67216 240499 55168 25593 Read speed, 4096 buffer (byte/sec) 109226 234057 53708 25323 Read speed, 8192 buffer (byte/sec) 187245 233189 54013 25183 Read speed, 32768 buffer (byte/sec) 374491 236343 53644 25123 Write speed, 512 buffer (byte/sec) 28187 215166 44181 43855 Write speed, 4096 buffer (byte/sec) 137970 182466 47211 46287 Write speed, 8192 buffer (byte/sec) 154202 179755 46832 46445 Write speed, 32768 buffer (byte/sec) 218453 187580 46930 46707 Notes: (1) Sun-30/50 timings by Rick Spanbauer. (2) All Amiga and Mac-II timings done by Fred Fish. (3) The Amiga 2000 uses an A2090 DMA controller, Workbench 1.3, and a Seagate ST277N (40 ms average access time). (4) The Mac-II uses an HD80SC (30 ms average access time) Comments: (1) I included both the Feb 88 and current Mac-II timings because the read figures were significantly different. I have no explanation for the discrepancy other than to note that the disk is probably now significantly fragmented, and I have since increased the number of I/O buffers to about 1000. (2) The Amiga timings I get for the relatively slow ST277N are about half of what have been reported by other people for faster drives (about 400-800 Kb per second maximum transfer rates). (3) Considering that the Amiga is a stock 68000 running at less than 8 MHz, using a 30% slower drive than the Mac-II, it seems obvious that disk I/O is not the Mac's strongest feature... :-) ====================================================================== /* ** 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 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. ** ** Amiga timings gathered thus far: ** ----------------------------------------------------------------------------- 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 #include #include #include #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 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) timer_init() { return(1); } timer_quit() { } 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; } 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 #include #include #ifdef MANX #include /* For Manx only */ #endif #define SCAN_ITER 5 #define RW_ITER 3 #define RW_SIZE (256*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; 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); } timer_quit() { CloseDevice(timermsg); DeleteExtIO(timermsg, sizeof(struct timerequest)); DeletePort(timerport); } 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)); } } 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/65536 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().. */ 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, 0}; void rw_test() { long i, j, k, maxsize, file, RDaccTime, WRaccTime, Dt; struct timeval t0, t1; 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 *)0){ printf("Could not get %d bytes of memory\n", maxsize); return; } for(k = 0; sptest[k] != 0; 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--) Write(file, p, sptest[k]); timer(&Dt); 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--) Read(file, p, sptest[k]); timer(&Dt); RDaccTime += Dt; Close(file); DeleteFile(filename); } printf("r/w speed:\t\tbuf %d bytes, rd %d byte/sec, wr %d byte/sec\n", sptest[k], (TIMER_RATE*RW_SIZE)/(RDaccTime/RW_ITER), (TIMER_RATE*RW_SIZE)/(WRaccTime/RW_ITER)); } FreeMem(p, maxsize); } 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\t%d seek/reads per second\n", (TIMER_RATE*cnt)/Dt); } Close(fd); DeleteFile(fname); } char tempname[OPEN_TEST_FILES][16]; 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:\tcreate %d files/sec, delete %d files/sec\n", (TIMER_RATE*OPEN_TEST_FILES)/cDt, (TIMER_RATE*OPEN_TEST_FILES)/dDt); printf("Directory scan:\t\t%d entries/sec\n", (TIMER_RATE*numRead)/sDt); #ifdef unix chdir(".."); rmdir(dirname); #else CurrentDir(oldlock); DeleteFile(dirname); #endif } 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(); } -- # Fred Fish, 1346 West 10th Place, Tempe, AZ 85281, USA # noao!nud!fishpond!fnf (602) 921-1113