Some questions about A/UX

Fred Fish fnf at fishpond.UUCP
Sat Nov 26 02:56:38 AEST 1988


In article <16775 at onfcanim.UUCP> dave at 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 <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

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(&current, 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 <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         (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



More information about the Comp.unix.aux mailing list