December 94 - PRINT HINTS
PRINT HINTS
Improving QuickDraw GX Printer Driver Performance
DAVE HERSEY
In this column, we go spelunking in the frost-covered caverns of QuickDraw GX. We'll
discover how QuickDraw GX I/O buffering works and how to use that knowledge to
squeeze optimal performance from a printer driver, whether PostScriptTM, raster,
or vector. We'll also learn how to find (and avoid) the common bottlenecks.
Suppose you've been working on your first QuickDraw GX printer driver, and the big
moment has arrived. Your printer's innards begin to whir and spin, and your heart
beats a little faster. Your driver is actually printing! As you see that image being
drawn on the page, your breathing quickens, and then . . . the printer stops. You run to
your Macintosh to see if your driver has crashed (again), but no, not this time. A few
seconds later the printer starts up again. And stops. And starts. This repeats until,
several minutes later, the page is finished.
What's going on? Is your printer defective? Maybe. But then again, the problem may
lie elsewhere. You probably have a data delivery problem on your hands. For one
reason or another, the data isn't getting to the printer fast enough to keep it busy. To
understand why, we need to look at what goes on behind the scenes when a driver tells
QuickDraw GX to send data to your printer.
Your first reaction might be, "Ah, I need to implement some sort of asynchronous I/O
to keep a steady stream of data going to my printer." That's a good thought, but
QuickDraw GX already provides asynchronous I/O. Let's look a little deeper.
There are four QuickDraw GX printing messages that are used to implement buffering:
• GXBufferData -- sent to move data into an available buffer
• GXWriteData -- sent to write data to the printer immediately without
buffering it first
• GXDumpBuffer -- sent to move a buffer full of data to the printer
• GXFreeBuffer -- sent to ensure that a buffer has been processed and is
available for new data
How do you get GXBufferData and GXFreeBuffer to work asynchronously, so that the
driver's data is sent to the printer as fast as possible? GXBufferData, in its default
implementation, already works asynchronously. However, GXFreeBuffer has to work
synchronously. Let's look at why.
In the following figures, assume that we have a driver with four buffers, and that at
every time interval (a, b, c, and so on) half of a buffer can be filled by the driver. (In
reality, the timeit takes to fill a buffer will vary as rendering time varies.)
First, let's say that the device can't process the data fast enough to empty out the first