/* %W% %G% %U% */ /* *************************************************** */ /* METAGRAPHICS SOFTWARE CORPORATION (c) 1992 */ /* FILE: GRAFSPED.C */ /* Graphs performance of disk bitmaps with varying */ /* swap buffer sizes */ /* *************************************************** */ /* ============================================================ This sample program can be used to fine tune your swap buffer sizes when using disk based bitmaps. Disk bitmaps use an area of conventional memory to draw into. This area represents a small 'band' of the total bitmap. When a part of the disk bitmap is to be modified, MetaWINDOW writes the old band in memory to the disk, and reads a new one from the disk into memory. This 'swapping' process is repeated many times while you draw. The optimum size of the swap buffer area is highly dependent on what you draw, and the disk hardware and software in use on the machine at the time. If the swap buffer is too small, drawing operations that span the swap buffer will cause many swaps to occur. If the swap buffer is too large, the time it takes to swap each buffer out will be sluggish (the whole swap buffer is written even if just one pixel in it changed). The ideal swap size is one that will just encompass the locality that you modify in each drawing operation. How can you calculate the optimum size for a swap buffer? You can't. You have to measure the performance of different size swap buffers under real world circumstances. That's just what this sample is for. You should replace the function diskmap() with one that matches what you are using the disk bitmap for. You then set the define INCSWAP to the amount of memory you would like to increase the swap buffer by each try, and set the define NUMSWAP to the number of times to try for. At the end of the run, a graph is displayed showing you the relative performance for each size of swap buffer size. Happy swapping! ============================================================ */ #define INCSWAP 10000L /* size to increment swap each try */ #define NUMSWAP 6 /* number of iterations to try for */ #include #include #include #include #include #include #include #include "metawndo.h" /* master MetaWINDOW include file */ #include /* special stack size declaration if using Turbo or Borland C++ */ #if TurboC extern unsigned _stklen = 14336U; /* stack size 14K */ #endif int GrafixCard, GrafixInput; int diskmap( long ); void report( void ); grafMap *offscrMap, *theMap; grafPort *offscrPort, *thePort; long times[NUMSWAP]; void main( int argc, char *argv[] ) { int i; long T1, T2, swapsize; /* Init system */ MetQuery(argc,argv); i = InitGraphics( GrafixCard ); if(i !=0 ) GrInitErr(i); /* display reason for no go */ GetPort(&thePort); theMap= thePort->portMap; SetDisplay(GrafPg0); /* Switch to graphics */ swapsize = 0; for( i = 0; i < NUMSWAP; i++ ) { EraseRect( &(thePort->portRect) ); swapsize += INCSWAP; T1 = biostime( 0, 0L ); diskmap( swapsize ); T2 = biostime( 0, 0L ); if( T1 > T2 ) times[i] = T1 - T2; else times[i] = T2 - T1; } report(); getch(); SetDisplay(TextPg0); /* Switch to alpha mode */ i=QueryError(); /* Show MetaWINDOW errors */ printf("QueryError=%d/%d",i >> 7,i & 127); StopGraphics(); exit(i); } void report( void ) /* generate a report screen */ { int i, y, xlabsiz, ylabsiz; char buf[80]; long max, min; rect vR, bR; // DrawString( "Time" ); EraseRect( &(thePort->portRect) ); /* find min and max times */ max = 0; min = 0x7FFFFFFFL; for( i = 0; i < NUMSWAP; i++ ) { if( times[i] < min ) min = times[i]; if( times[i] > max ) max = times[i]; } /* put on labels */ xlabsiz = thePort->txFont->chHeight; ylabsiz = StringWidth( "Swap " ); /* label X axis */ i = (thePort->portRect.Xmax + ylabsiz) / 2; MoveTo( i, thePort->portRect.Ymax ); TextAlign( alignCenter, alignBottom); DrawString( "Time" ); MoveTo( ylabsiz, thePort->portRect.Ymax ); TextAlign( alignLeft, alignBottom); sprintf( buf, "%ld", min); DrawString( buf ); MoveTo( thePort->portRect.Xmax, thePort->portRect.Ymax ); TextAlign( alignRight, alignBottom ); sprintf(buf, "%ld", max); DrawString( buf ); /* label Y axis */ i = (thePort->portRect.Ymax + xlabsiz)/2; MoveTo( 0, i ); TextAlign( alignLeft, alignBottom); DrawString("Swap"); MoveTo( 0, i ); TextAlign( alignLeft, alignTop); DrawString("Size"); MoveTo( 0, 0 ); TextAlign( alignLeft, alignTop); sprintf( buf, "%ld", INCSWAP ); DrawString(buf); MoveTo( 0, thePort->portRect.Ymax - xlabsiz ); TextAlign( alignLeft, alignBottom); sprintf( buf, "%ld", INCSWAP*NUMSWAP ); DrawString(buf); /* graph data */ PortSize( thePort->portRect.Xmax - ylabsiz, thePort->portRect.Ymax - xlabsiz ); MovePortTo( ylabsiz, 0 ); SetRect( &vR, (int) min, 0, (int) max, NUMSWAP * 10 ); VirtualRect( &vR ); vR.Xmax--; vR.Ymax--; FrameRect( &vR ); for( i = 0; i < NUMSWAP; i++ ) { y = i * 10; SetRect( &bR, (int) min, y, (int) times[i], y + 5 ); PaintRect( &bR ); } } /* ----------------------------------------------------------- This is the routine that you customize to emulate the size of disk bitmap you would be using, as well as the kind of operations you expect to perform on your disk bitmap. This sample shows you an example of a disk bitmap that is the same size as the screen bitmap (global grafMap pointer theMap). This sample does a large fill, a frame, some lines, a small amount of text, and a copy to the display bitmap. ----------------------------------------------------------- */ int diskmap( long swap ) { rect sR, fR; /* allocate the offscreen structures */ offscrMap = (grafMap *)malloc(sizeof(grafMap)); offscrPort = (grafPort *)malloc(sizeof(grafPort)); if(offscrPort == NULL || offscrMap == NULL ) { printf("ERROR: Unable to malloc offscreen structures"); exit(1); } /* set same size as screen bitmap */ offscrMap->pixWidth = theMap->pixWidth; offscrMap->pixHeight = theMap->pixHeight; offscrMap->pixBits = theMap->pixBits; offscrMap->pixPlanes = theMap->pixPlanes; offscrMap->pixResX = theMap->pixResX; offscrMap->pixResY = theMap->pixResY; /* set swap size using passed argument */ offscrMap->mapHandle= swap; /* make a disk bitmap */ if( InitBitmap( cDISK, offscrMap ) ) { CloseBitmap( offscrMap ); printf("\nERROR: Unable to launch offscreen system"); return(1); } /* put this bitmap in its own port */ InitPort(offscrPort); PortBitmap(offscrMap); PortSize( offscrMap->pixWidth, offscrMap->pixHeight ); ClipRect( &offscrPort->portRect); /* Offscreen system is all set, do some drawing to it */ DupRect( &offscrPort->portRect,&sR); PenColor(Red); BackColor(LtGray); FillRect( &sR,30 ); /* Fill it */ DupRect( &sR, &fR); fR.Xmax--; fR.Ymax--; PenColor(Green); FrameRect(&fR); /* Frame it */ PenColor(Blue); MoveTo(fR.Xmin, fR.Ymin); LineTo(fR.Xmax, fR.Ymax); MoveTo(fR.Xmax, fR.Ymin); LineTo(fR.Xmin, fR.Ymax); PenColor(Black); MoveTo(5,20 ); DrawString("Offscreen is easy with CopyBlit() and InitBitmap()"); /* copy to screen */ CopyBlit(offscrPort,thePort,&offscrPort->portRect,&offscrPort->portRect); /* shut down */ if( CloseBitmap( offscrMap ) ) printf("\nError closing grafMap offscrMap"); free(offscrMap); free(offscrPort); /* set back to the screen grafPort */ SetPort(thePort); return(0); } #include "MetQuery.C"