home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-09-30 | 7.1 KB | 184 lines | [TEXT/KAHL] |
- I want to get Macintosh programmers up in arms about the shameful state
- of 3rd party Macintosh hard disk driver software. The Mac operating system
- supports a wonderful feature that could let our programs run much faster,
- but the developers of disk driver software have cheated us out of it.
-
- I am referring to asynchronous disk i/o. According to Inside Mac, if you do
- a PBRead(&ioBlock, TRUE), or, a PBWrite(&ioBlock, TRUE), the call
- should schedule the i/o, and return almost immediately, and when the i/o
- is actually done, the system will set some fields in the ioBlock, and call the
- completion routine associated with the ioBlock.
-
- This is useful because the disk i/o is mostly waiting for the disk heads to
- seek to the right track. That waiting time could be spent doing useful
- processing (particularly under a future version of multifinder, which
- could give that time to another task.) That is the traditional use of disk i/o
- time in a multi-tasking operating system.
-
- In addition, there are special uses of asynchronous i/o that only make sense in
- a personal system. In a multi-user system, your programs makes a disk request,
- and waits, meanwhile the o.s. runs somebody else's program. This is known as
- "demand page faulting" and is the worst possible way to organize a personal
- computer system, because often you only care about _one_ program being fast:
- the one you are interacting with right now. When that program needs something
- from disk, it doesn't tell the O.S. until it actually needs it, and it has to
- twiddle its thumbs while the O.S. fetches it.
-
- I've got papers in my files from 10 years ago on compiling number-crunching
- programs for personal computers to pre-fetch disk based arrays so that the
- program _never_ has to wait for the disk: the pieces of the arrays it needs
- are already in memory by the time it needs them. This is known as
- "pre-fetching", and judicious use of it lets a 1 Megabyte RAM machine with a
- 40 Meg disk run 99% as fast a 40 Meg RAM machine, when crunching 40Meg
- worth of arrays.
-
- The Macintosh has a chance to show clear superiority over other brands here.
- MSDOS does not support asynchronous disk i/o. Unix does not support
- asynchronous disk i/o. Don't you think Apple would love to have
- number-crunching programs that run fine on a Macintosh, but run
- 100 times slower for problems of the same size when run on a 386 or a Sun?
-
- But, most third party developers of hard disks simply didn't implement
- asynchronous disk i/o. The hard disk makers cheat the public by leaving this
- feature out, and we software developers are left without a valuable tool.
-
- Apple's floppy disk drivers support asynchronous i/o. The simple test program
- included here shows that for this example, more than 99% of the time to do a
- disk read happens between the end of the scheduling part of the PBRead, and the
- end of the actual data transfer. Now admitedly some of that time is spent
- servicing the drive, but much of that time could be spent getting work done.
-
- Let us create a hall of shame. Does your hard disk support asynchronous i/o?
- if not, please post their name here, so we can complain. So we can get some
- action, so we can get disk based programs that run at all-RAM speeds!
-
- (I compiled the following program with LightSpeed C 3.0,
- linked with MacTraps and stdio.)
-
- ----------- cut here --------------------- cut here -------------------------
- /* Asynch i/o - program to report if your hard drive supports asynch disk i/o.
- */
- #include <stdio.h>
- #include <OSUtil.h>
- #include <FileMgr.h>
-
- char *header = "Test of Asynchronous Disk I/O, Version 1.0,\n\
- Copyright ⌐ 1988, by David Phillip Oster\n\
- Mosaic Codes, Suite 2036, 2140 Shattuck Ave., Berkeley CA 94704, USA\n\n\
- You may copy this program freely, except that Think, Inc.\n\
- retains copyright to libraries used by this program.\n\n\
- Warning: times reported by this program are only accurate to the \n\
- nearest 0.02 second\n\n\
- Start Test: reading 100k from the System File.\n\n";
-
- char *congrat1 = "Congratulations: your drive supports asynchronous i/o.\n";
- char *congrat2 =
- "Your drive would have let you use %.1f%% of otherwise wasted time.\n";
-
- unsigned long readComplete = 0; /* time read actually finshes trasnfering data */
- Ptr ioBuf; /* buffer for access path */
- IOParam io; /* io parameter block for all our disk i/o */
- int ioCnt = 0; /* count of i/o calls, for error checking */
-
- char *ioName[] = {
- "SysEnvirons",
- "PBOpenRF",
- "PBGetEOF",
- "PBRead",
- "AwaitFinish"
- };
-
- /* Completion -
- */
- pascal void Completion(){
- SetUpA5();
- readComplete = TickCount();
- RestoreA5();
- }
-
- /* AwaitFinish -
- */
- OSErr AwaitFinish(){
- unsigned long start;
-
- start = TickCount();
- while(io.ioResult > 0){
- /* we do nothing in this toy program. In a real program, */
- /* we would do useful work here */
- if( (unsigned long) TickCount() - start > 1500L){
- printf("TOO BAD: read time out, ioResult =%d\n", io.ioResult);
- break;
- }
- }
- return noErr;
- }
-
- /* macro to propagate i/o errors
- */
- #define IO(expr)if(noErr == val){val = expr;ioCnt++;}
-
- main(){
- unsigned long start, readReturned;
- long siz;
- OSErr val, oVal;
- SysEnvRec world;
- Ptr buffer;
-
- printf(header);
- SysEnvirons(1, &world);
- val = noErr;
- if(noErr == val){ioBuf = NewPtr(522L); val = MemError(); }
-
- io.ioCompletion = NULL;
- io.ioNamePtr = (StringPtr) "\pSystem";
- io.ioVRefNum = world.sysVRefNum;
- io.ioVersNum = 0;
- io.ioPermssn = fsRdPerm;
- io.ioMisc = ioBuf; /* get speed: give this file its own buffer */
-
- /* file manager can't take asynch calls */
- IO(oVal = PBOpenRF(&io, FALSE));
- IO(PBGetEOF(&io,FALSE));
- siz = (long) io.ioMisc;
- if(siz < 102400L){
- siz = 102400L;
- }
- if(noErr == val){buffer = NewPtr(siz); val = MemError(); }
-
- start = TickCount();
-
- io.ioCompletion = (ProcPtr) Completion;
- io.ioBuffer = buffer;
- io.ioReqCount = siz;
- io.ioPosMode = fsAtMark;
- /* disk manager asynch call */
- IO(PBRead(&io, TRUE));
- readReturned = TickCount();
- IO(AwaitFinish());
- if(noErr == oVal){ val = PBClose(&io, FALSE); }
- if(readReturned == start){ /* time was too small to measure accurately */
- start--;
- }
- if(noErr == val){
- printf("Read Returned after %.2f seconds\n", (readReturned-start)/60.);
- if(0 == readComplete){
- printf("TOO BAD: Completion routine never called.\n");
- }else if(readComplete < readReturned){
- printf("TOO BAD: Completion routine called before Read returned.\n");
- }else{
- printf("Read complete after %.2f seconds\n",
- (readComplete-start)/60.);
- if(readComplete <= readReturned){
- printf("TOO BAD: no asynchronous i/o here.\n");
- }else{
- printf(congrat1);
- printf(congrat2,
- (readComplete-readReturned)*100./(readComplete-start));
- }
- }
- }else{
- printf("I/O Error Occurred, %s, Error = %d", ioName[ioCnt], val);
- }
- }
-
-