Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!watmath!clyde!rutgers!mit-eddie!genrad!decvax!linus!philabs!sbcs!root
From: root@sbcs.UUCP
Newsgroups: comp.sys.amiga
Subject: The great DMA -vs- non DMA disk controller war, and ...
Message-ID: <250@sbcs.UUCP>
Date: Tue, 9-Dec-86 22:42:57 EST
Article-I.D.: sbcs.250
Posted: Tue Dec 9 22:42:57 1986
Date-Received: Sun, 14-Dec-86 06:42:32 EST
Distribution: net
Organization: Computer Science Dept, SUNY@Stony Brook
Lines: 694
Here is a disk benchmark program I whipped up while pondering whether
a DMA disk controller really matters with Commodore's current (old Unix
style) disk format. Any proud owners of a shiny, new Byte by Byte
(or any other derivative of the C-A DMA disk controller) want to take
a shot at running this program? I would also like to hear from folks
running the MicroScience (?) drive which hangs off the parallel port.
Rick Spanbauer
SUNY/Stony Brook
----------------------------------------------------------------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# diskperf.c
# diskperfa.uu
# This archive created: Tue Dec 9 22:29:09 1986
export PATH; PATH=/bin:$PATH
if test -f 'diskperf.c'
then
echo shar: over-writing existing file "'diskperf.c'"
fi
cat << \SHAR_EOF > 'diskperf.c'
/*
** 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.
**
** 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
#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 = 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 = 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 = 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();
}
SHAR_EOF
chmod +x 'diskperf.c'
if test -f 'diskperfa.uu'
then
echo shar: over-writing existing file "'diskperfa.uu'"
fi
cat << \SHAR_EOF > 'diskperfa.uu'
begin 644 diskperfa
M #\P # ( 25 *GP /I $E4CG?_XC
MSP PO""\ < B/ *GPB? 9R2B>2!8 (BP%')__PC^ $ !G"\
M2'D 3KH1UE!/(\ &@3KH.MBYY #$S??_Y.=4Y6 !"IT*G3KD
M D04$\CP )^Q*N0 )^QF!G 8 B$AX "@O.0 )^Q.N0 ")103R/
M !I$JY !I&82+SD "?L3KD G.6$]P &!40J !2'D
M H3KD !'P3^\ $$J 9R0O.0 )^Q.N0 "0 :0CZ 4 !J' !3EY.=4Y6 O.0 :1.N0 $8A8
M3TAX "@O.0 :1.N0 "-Q03R\Y G[$ZY )SEA/3EY.=4Y6__@N@B!Y
M !I#%\ H '"\Y !I$ZY 1G%A/('D &D+6@ (/_\2JX "&8<(#D
M &D="#0@B! (^@ ! * CT )_Q@3$AY G_" Y !I'0@T((O $ZY
M 2/%!/('D &D("@ (-" ) #EBM"") @>0 :0@* D(CP 8:@3KD
M X(U( @;@ ((((D+O_X3EY.=4Y6__A(> /M+RX "$ZY 0F%!/+4#__&8$
M< !@)DAY H!"\N__Q.N0 $&Q03RU __@O+O_\3KD !$86$\@+O_X3EY.
M=4Y6__0M>0 *0C_]%*Y I""UN C_^$JN QG)"UY $/_\8!(@;O_X
M(F[__!"14J[__%*N__@@;O_\2A!FYBU\ -?_\8!(@;O_X(F[__!"14J[_
M_%*N__@@;O_\2A!FYB!N__@@+O_TX(!R#\"!0 &!.N0 "B!@ &N0J=A /V66$\@+O_TY8!!^0 !0B, @
M(#P ! 3KD V,+4#__& F("[_].6 0?D 4+S ( "\N_\PO+O_L3KD
M !$L3^\ #%.N__Q*KO_\;M1(;O_@80#]/EA/("[_X-&N_^0O+O_L3KD ! <
M6$](> /M2&[_C$ZY 0M%!/+4#_[&842&[_C$AY =4ZY *(& 1!"
MIV$ _/A83R N__3E@$'Y %"(P" @/ $ !.N0 #8PM0/_\8"8@+O_T
MY8!!^0 !0O, @ +R[_S"\N_^Q.N0 $.!/[P ,4Z[__$JN__QNU$AN_^!A
M /R@6$\@+O_@T:[_Z"\N_^Q.N0 $!Q83TAN_XQ.N0 $%A83U*N__@,K@
M /_^&T _IP@+O_D<@-.N0 #8PB " \ "@ $ZY -C"\ ("[_Z'(#3KD
M V,(@ @/ H !.N0 #8PO " N__3E@$'Y %"\P" !(>0 (A.N0
M"B!/[P 04J[_]" N__3E@$'Y %$JP" !F /X@+R[_\"\N_\Q.N0 $<10
M3TY>3G5.5O^H2'@ 4AN_\!A /S$4$](> /N2&[_P$ZY 0M%!/+4#_N&86
M2&[_P$AY PDZY *(%!/8 \'(@+4'_O& D2'@@ $AY '["\N_[A.
MN0 $2Q/[P ,#( " 9@I3KO^\2J[_O&[62J[_O&8 )Y"KO^P0J=A /MH
M6$\M? 0#_J$*N_ZQ2KO^P2'C__R\N_ZPO+O^X3KD !#\3^\ #$AX %(
M>0 !^PO+O^X3KD !#@3^\ #" N_ZC1KO^L#*X ! _ZQMO.6 +4#_J RN
M $ /^H;ZA(;O^T80#Z_EA/("[_L-" (@#E@="!(B[_M$ZY -C"\ 2'D
M #73KD H@4$\O+O^X3KD ! <6$](;O_ 3KD !!86$].7DYU3E;_F$AX
M %(;O_ 80#[E%!/2&[_P$ZY 0,%A/+4#_O"\ 3KD !!$6$\M0/^X0J[_
MJ$*G("[_J.F !H &L+P!A /M<4$]2KO^H#*X !D_ZAMW$*G80#Z7%A/
M0J[_J$AX ^X@+O^HZ8 &@ :PO $ZY 0M%!/+4#_H&8<2'D &L2&[_
MP$AY ! DZY *($_O Q@&B\N_Z!.N0 $!Q83U*N_Z@,K@ &3_J&VJ
M2&[_M&$ ^?A83T*G80#Y\%A/<@$M0?^<0J[_J$*N_Z0@+O^HZ8 &@ :PO
M &$ ^G!83TJ 9P12KO^<4J[_I RN 9/^D;=92KO^H#*X %_ZAMQ$AN
M_ZQA /F@6$]"IV$ ^9A83T*N_Z@@+O^HZ8 &@ :PO $ZY 06%A/4J[_
MJ RN 9/^H;=Q(;O^P80#Y9EA/(#P /H(B[_L$ZY -C"\ (#P /H
M(B[_M$ZY -C"\ 2'D $83KD H@3^\ #" N_YS0@"( Y8'0@2(N_ZQ.
MN0 #8PO $AY !5DZY *(%!/+R[_N$ZY 01%A/2&[_P$ZY 06%A/
M3EY.=4Y6 !.N0 %1*@&822'D %W3KD H@6$]P & B#*X ! AO
M#"!N PCZ $ $&$ _?QA /S(80#Z4$Y>3G4 $Y6__Q*K@ (9Q9(>0 !
M $O+@ ,80 (LE!/+4#__&8$< !@("!N__P1? % @@;O_\0B@ "2!N__PA
M;@ ( X@+O_\3EY.=4Y6 @;@ ($7P _P ((&X "'+_(4$ %"!N @A00 8
M+RX #"\N AA B^4$].7DYU !.5O_P+HU(>/__80 (6%A/'4#_]PP __]F
M!G 8 F$AY $ 4AX ")A @@4$\M0/_X9A00+O_W2(!(P"\ 80 (BEA/
M< !@;"!N__@A;@ ( H@;O_X$6X #P )(&[_^!%\ 0 ""!N__A"* .(&[_
M^!%N__\ #T*G80 ((EA/(&[_^"% !!*K@ (9PPO+O_X80 'HEA/8!8J;O_X
M[_=& F ,!P E9P84QV E1![O]T
MM =? @_V<,
M%0 M9@92+O]F4HT,%0 P9@@=? P_V=2C0P5 "IG(GH $!U(@$C ?C"0ARP
M;2)^";R';AS:A2(%Y8':@=J&8.!2C1 =2(!(P'XPD([_:"U(__Q@+" "
M(@-.N@*<+ @;O_\?@J\AVP$<#!@ G!7T(80@%*N__P@ B(#3KH"%B0 2H)F
MT$'N_V@@+O_\L(AC*E.N__P@;O_\%-!@Z"U,__Q8C'P (&[__%*N__P4T&8"
M4XI2AGX$O(=MZD'N_W0M2/_\( J0KO_\FH L!6P"? !*+O]F9@)$AA N_V=(
M@$C +P!(4R\&E>[__"\*+R[__&%X3^\ %& _=XM7/_\9@@M? 93__"P$
M9@8L/ ?_\D;O_\2A)GJ%.&;:12BF#T*%0J7& 4%/P )6 .>'5S'68 _9Y![O]TM3G5.5@ 2.* XH$"@'__
M__\"@7____\,@0 ! !L /_H@,$"@ __\B TZZ !:T@&P"D(.0@D2 3-\
M#$Y>3G4 $Y6 !(YS ) F 4* , + PS("2$+$PTA#PL/2@DA!0D'0@4S?
M Q.7DYU3E;_Y$C7., N+@ (*FX #$*G80 "H%A/+4#__"! 2J@ K&< ,@@
M0" H *SE@"U __AA %8(\ "?T80 !EB/ G^"/ G\"!N__@L* 0
MY88H1B9\ J6!P<2(9(QG(@O(%O!GP?8 (6W" &4X9*@&[V0AL@.0 *GCE
M@$'Y I$"&\ J6 @ 4KD "IX#(< $ ;P8N/ /\F? *5A@/ P5
M "!N"%*-4X=*AV[R2H=O*B Y J>.6 0?D "D0(8L( %*Y J>& *#!4
M(&\(%MU3ATJ';O)"&TJ';LH@.0 *GCE@$'Y I$$*P" 1"ITAY I$"\Y
M J>&$ ^$)/[P ,3.XXP/_D3EY.=0 +PXB+P (+'D &@3J[_W"Q?3G4O
M#B(O @L>0 :!.KO^(+%].=2\.(B\ ""QY !H$ZN_X(L7TYU+PXB+P (
M+'D &@3J[_N"Q?3G5(YR "3.\ !@ ,+'D &@3J[_FDS?0 1.=0 +PXL
M>0 :!.KO_*+%].=4CG( ),[P & PL>0 :!.KO^L3-] !$YU !(YR "
M3.\ !@ ,+'D &@3J[_XDS?0 1.=0 +PXL>0 :!.KO_$+%].=4CG, ),
M[P . ! L>0 :!.KO_63-] #$YU !(YS "3.\ #@ 0+'D &@3J[_ODS?
M0 Q.=0 +PXB+P (+'D &@3J[_IBQ?3G5(YS "3.\ #@ 0+'D &@3J[_
MT$S?0 Q.=0 +PXB;P (+'D &<3J[^GBQ?3G4O#DSO , ""QY !G$ZN
M_SHL7TYU O#B O @L>0 9Q.KOZV+%].=2\.(F\ ""QY !G$ZN_CXL
M7TYU+PXB;P (+'D &<3J[^."Q?3G4O#B)O @L>0 9Q.KO[:+%].=2\.
M(F\ "" O PL>0 9Q.KO\N+%].=2\.("\ ""QY !G$ZN_K L7TYU+PX@
M;P (3.\" 0 ,(B\ %"QY !G$ZN_D0L7TYU O#B)O @@+P ,+'D &<
M3J[]V"Q?3G4O#B)O @L>0 9Q.KOZ8+%].=2\.3.\# (+'D &H3J[_
MT"Q?3G4 ^P Z %X "$ H +X #2 Y
M 0X $@ !+@ 5( &: !Q@ >@ ($ "% S( -* #
M?@ Y8 .^ #X@ ! P 0< $- !%P 2 $J@ !+8 34
M $X@ !/ 3^ %' !48 5L %A !:8 7R &"@ !E
M 9> &:@ !G8 :8 &I@ !O@ <6 ')@ ![@ ?B ']
M" ( @< (*@ "#8 A" (4@ "&( !P 0 8 2
M& "P T 0 $H !F ; 'X ", D@ )H "N
M N ,P #> \ /@ $( !&@ 2@ % !3 5H
M %L !>@ 8 &( !C@ :( &V !^@ B@ (P "0@
M F8 +T #"@ R -$ #D ZX /0 $+@ !$P 1N %
M# !18 4P %?@ !9P 8 &6 !KX ;P '!@ !Q =B
M 'L !_P @D (7 "'X QX ,\@ #/X T@ -. #50
M UL /- #SX ]$ /5@ #W@ ^ /A@ #XX ^B /O
M#\0 _. /Z@ #_( _^ 0! $"0 ! X 03 $& !!X 0
MC $*0 !# 0U $.P !$( 1( $3@ !%0 19@ $7P !&0
M 1I $;@ !'0 1Y $@( !(< 2, $D8 #\@ ^H
M !G9&]S+FQI8G)A0H 0V]U;&0@;F]T(&-R96%T92 E71E