home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / utildsk / asynch.sit / Asynch.text < prev   
Encoding:
Text File  |  1988-09-30  |  7.1 KB  |  184 lines  |  [TEXT/KAHL]

  1.     I want to get Macintosh programmers up in arms about the shameful state
  2. of 3rd party Macintosh hard disk driver software. The Mac operating system
  3. supports a wonderful feature that could let our programs run much faster,
  4. but the developers of disk driver software have cheated us out of it.
  5.  
  6.     I am referring to asynchronous disk i/o. According to Inside Mac, if you do
  7. a PBRead(&ioBlock, TRUE), or, a PBWrite(&ioBlock,  TRUE), the call
  8. should schedule the i/o, and return almost immediately, and when the i/o
  9. is actually done, the system will set some fields in the ioBlock, and call the
  10. completion routine associated with the ioBlock.
  11.  
  12.     This is useful because the disk i/o is mostly waiting for the disk heads to
  13. seek to the right track. That waiting time could be spent doing useful
  14. processing (particularly under a future version of multifinder, which
  15. could give that time to another task.) That is the traditional use  of disk i/o
  16. time in a multi-tasking operating system. 
  17.  
  18. In addition, there are special uses of asynchronous i/o that only make sense in
  19. a personal system.  In a multi-user system,  your programs makes a disk request,
  20. and waits, meanwhile the o.s. runs somebody else's program. This is known as
  21. "demand page faulting" and is the worst possible way to organize a personal
  22. computer system, because often you only care about _one_ program being fast:
  23. the one you are interacting with right now. When that program needs something
  24. from disk, it doesn't tell the O.S. until it actually needs it, and it has to 
  25. twiddle its thumbs while the O.S. fetches it.
  26.  
  27. I've got papers in my files from 10 years ago on compiling number-crunching 
  28. programs  for personal computers to pre-fetch disk based arrays so that the 
  29. program _never_  has to wait for the disk: the pieces of the arrays it needs
  30. are already in memory by the time it needs them. This is known as 
  31. "pre-fetching", and judicious use of it lets a 1 Megabyte RAM machine with a
  32. 40 Meg disk run 99% as fast a 40 Meg RAM machine, when crunching 40Meg
  33. worth of arrays.
  34.  
  35. The Macintosh has a chance to show clear superiority over other brands here.
  36. MSDOS does not support asynchronous disk i/o. Unix does not support
  37. asynchronous disk i/o. Don't you think Apple would love to have 
  38. number-crunching programs that run fine on a Macintosh, but run 
  39. 100 times slower for problems of the same size when run on a 386 or a Sun?
  40.  
  41. But, most third party developers of hard disks simply didn't implement
  42. asynchronous disk i/o. The hard disk makers cheat the public by leaving this
  43. feature out, and we software developers are left without a valuable tool.
  44.  
  45. Apple's floppy disk drivers support asynchronous i/o. The simple test program
  46. included here shows that for this example, more than 99% of the time to do a
  47. disk read happens between the end of the scheduling part of the PBRead, and the
  48. end of the actual data transfer.  Now admitedly some of that time is spent
  49. servicing the drive, but much of that time could be spent getting work done.
  50.  
  51. Let us create a hall of shame. Does your hard disk support asynchronous i/o?
  52. if not, please post their name here, so we can complain. So we can get some
  53. action, so we can get disk based programs that run at all-RAM speeds!
  54.  
  55. (I compiled the following program with LightSpeed C 3.0, 
  56. linked with MacTraps and stdio.)
  57.  
  58. ----------- cut here --------------------- cut here -------------------------
  59. /* Asynch i/o - program to report if your hard drive supports asynch disk i/o.
  60.  */
  61. #include <stdio.h>
  62. #include <OSUtil.h>
  63. #include <FileMgr.h>
  64.  
  65. char *header =     "Test of Asynchronous Disk I/O, Version 1.0,\n\
  66. Copyright ⌐ 1988, by David Phillip Oster\n\
  67. Mosaic Codes, Suite 2036, 2140 Shattuck Ave., Berkeley CA 94704, USA\n\n\
  68. You may copy this program freely, except that Think, Inc.\n\
  69. retains copyright to libraries used by this program.\n\n\
  70. Warning: times reported by this program are only accurate to the \n\
  71. nearest 0.02 second\n\n\
  72. Start Test: reading 100k from the System File.\n\n";
  73.  
  74. char *congrat1 = "Congratulations: your drive supports asynchronous i/o.\n";
  75. char *congrat2 = 
  76.    "Your drive would have let you use %.1f%% of otherwise wasted time.\n";
  77.  
  78. unsigned long readComplete = 0;    /* time read actually finshes trasnfering data */
  79. Ptr     ioBuf;                     /* buffer for access path */
  80. IOParam io;                        /* io parameter block for all our disk i/o */
  81. int ioCnt = 0;                     /* count of i/o calls, for error checking */
  82.  
  83. char *ioName[] = {
  84.     "SysEnvirons",
  85.     "PBOpenRF",
  86.     "PBGetEOF",
  87.     "PBRead",
  88.     "AwaitFinish"
  89. };
  90.  
  91. /* Completion -
  92.  */
  93. pascal void Completion(){
  94.     SetUpA5();
  95.     readComplete = TickCount();
  96.     RestoreA5();
  97. }
  98.  
  99. /* AwaitFinish -
  100.  */
  101. OSErr AwaitFinish(){
  102.     unsigned long start;
  103.  
  104.     start = TickCount();
  105.     while(io.ioResult > 0){
  106.         /* we do nothing in this toy program. In a real program, */
  107.         /* we would do useful work here */
  108.         if( (unsigned long) TickCount() - start > 1500L){
  109.             printf("TOO BAD: read time out, ioResult =%d\n", io.ioResult);
  110.             break;
  111.         }
  112.     }
  113.     return noErr;
  114. }
  115.  
  116. /* macro to propagate i/o errors 
  117.  */
  118. #define IO(expr)if(noErr == val){val = expr;ioCnt++;}
  119.  
  120. main(){
  121.     unsigned long start, readReturned;
  122.     long siz;
  123.     OSErr val, oVal;
  124.     SysEnvRec world;
  125.     Ptr buffer;
  126.  
  127.     printf(header);
  128.     SysEnvirons(1, &world);
  129.     val = noErr;
  130.     if(noErr == val){ioBuf = NewPtr(522L); val = MemError(); }
  131.  
  132.     io.ioCompletion = NULL;
  133.     io.ioNamePtr    = (StringPtr) "\pSystem";
  134.     io.ioVRefNum    = world.sysVRefNum;
  135.     io.ioVersNum    = 0;
  136.     io.ioPermssn    = fsRdPerm;
  137.     io.ioMisc       = ioBuf;    /* get speed: give this file its own buffer */
  138.  
  139.             /* file manager can't take asynch calls */
  140.     IO(oVal = PBOpenRF(&io, FALSE));
  141.     IO(PBGetEOF(&io,FALSE));
  142.     siz = (long) io.ioMisc;
  143.     if(siz < 102400L){
  144.         siz = 102400L;
  145.     }
  146.     if(noErr == val){buffer = NewPtr(siz); val = MemError(); }
  147.  
  148.     start = TickCount();
  149.  
  150.     io.ioCompletion = (ProcPtr) Completion;
  151.     io.ioBuffer     = buffer;
  152.     io.ioReqCount   = siz;
  153.     io.ioPosMode    = fsAtMark;
  154.             /* disk manager asynch call */
  155.     IO(PBRead(&io, TRUE));
  156.     readReturned = TickCount();
  157.     IO(AwaitFinish());
  158.     if(noErr == oVal){    val = PBClose(&io, FALSE);    }
  159.     if(readReturned == start){    /* time was too small to measure accurately */
  160.         start--;
  161.     }
  162.     if(noErr == val){
  163.         printf("Read Returned after %.2f seconds\n", (readReturned-start)/60.);
  164.         if(0 == readComplete){
  165.             printf("TOO BAD: Completion routine never called.\n");
  166.         }else if(readComplete < readReturned){
  167.             printf("TOO BAD: Completion routine called before Read returned.\n");
  168.         }else{
  169.             printf("Read complete after %.2f seconds\n", 
  170.                 (readComplete-start)/60.);
  171.             if(readComplete <= readReturned){
  172.                 printf("TOO BAD: no asynchronous i/o here.\n");
  173.             }else{
  174.                 printf(congrat1);
  175.                 printf(congrat2, 
  176.                     (readComplete-readReturned)*100./(readComplete-start));
  177.             }
  178.         }
  179.     }else{
  180.         printf("I/O Error Occurred, %s, Error = %d", ioName[ioCnt], val);
  181.     }
  182. }
  183.  
  184.