[comp.sys.mac.programmer] Quickdraw speed

kw1r+@andrew.cmu.edu (Kevin Whitley) (05/09/88)

I've been working on a program that draws a lot of lines to the screen (using
LineTo & friends) and now I'm trying to speed it up.  I wrote a little test
program in Lightspeed C whose relevant part is:

ii = 10000;
timer = TickCount();
while (--ii >= 0)
        {
        MoveTo(0,0);
        LineTo(1,0);
        LineTo(2,0);
        }
timer = TickCount() - timer;

When I execute this fragment with varying numbers of LineTo calls I get the
result that a call to LineTo which draws 1 pixel on a horizontal line costs
around 0.4 milliseconds on a Mac II, about twice that much on an SE.  Am I
doing something wrong?  This seems MUCH too slow.  My non-Mac colleagues have
been derisive about this speed.  What can I do to speed it up?

Thanks,

Kevin Whitley
Carnegie-Mellon University
kw1r@andrew.cmu.edu

steele@unc.cs.unc.edu (Oliver Steele) (05/10/88)

kw1r+@andrew.cmu.edu (Kevin Whitley) writes:
>When I execute this fragment with varying numbers of LineTo calls I get the
>result that a call to LineTo which draws 1 pixel on a horizontal line costs
>around 0.4 milliseconds on a Mac II, about twice that much on an SE.

First of all, the fact that the line is only 1 pixel long doesn't make
your test go much faster than if the pixel were 10 or 100 pixels long,
since you're also measuring the overhead of the trap dispatcher and the
overhead to check for clipping, depth of bitmap, penpat, etc.

I get, for horizontal lines, that each MoveTo/LineTo pair takes
	length		milliseconds
	  1		.52
	 10		.52
	100		.53
	500		.54
which begins to look respectable; it isn't as if the Mac spends half a
millisecond on each pixel of a line.  Quickdraw is optimized for
horizontal lines, though; for vertical:
	 10		.83
	100		.75
and diagonal (length in x or y delta):
	 10		.83
	100	       2.84 !
.

>My non-Mac colleagues have been derisive about this speed.
I think it's pretty good, when you consider that this includes clipping
time and a check for arbitrary patterns, colors, and sizes.  If your non-
Mac colleagues work at Pixar or E&S, though, they probably have a right
to be derisive.  (Sorry; my Mac bigotry is showing.)

>What can I do to speed it up?
1) Keep in mind that the trap dispatcher on a II takes about .05
   milliseconds per call, and that each MoveTo takes that .05
   milliseconds plus another .01 to do its stuff.  If your lines have
   adjacent end points and you can draw them in that order, you'll save
   .06 milliseconds per line.

2) Forgo the trap dispatcher all together, by getting the address of
   MoveTo and LineTo OUTSIDE of the loop and calling these addresses
   inside the loop.  This saves you .1 millisecond for each line, if
   you need to MoveTo each beginning.  Here's how to do this in LSC:

#include <OSUtil.h>

#define	MoveToTrapNum	0x93
#define	LineToTrapNum	0x91
...
	long	MoveToAddr, LineToAddr;

	MoveToAddr = NGetTrapAddress(MoveToTrapNum,ToolTrap);
	LineToAddr = NGetTrapAddress(lineX,ToolTrap);
...
	while (--i >= 0) asm {
		move.w	#0,-(a7)
		move.w	#0,-(a7)
		move.l	MoveToAddr,a0
		jsr	(a0)
		move.w	#0,-(a7)
		move.w	#100,-(a7)
		move.l	LineToAddr,a0
		jsr	(a0)
		}

Don't use CallPascal(0,0,MoveToAddr):  CallPascal takes longer than
the trap dispatcher does.

It's probably not worth going to too much effort to optimize this any
more, or to try getting around QuickDraw unless you're writing an arcade
game and are really sure what you're doing.  You'll usually find that
it's your generation or transformation of the lines, and not their actual
rendering, that is slowing you down.  (Speaking from my own experience,
not an indictment of your skills.)

 ---------------------------------------------------------------------------
 Oliver Steele					  ...!decnet!mcnc!unc!steele
 UNC-CH							   steele@cs.unc.edu

 "We made it structured, and now it doesn't work." -- Brice Tebbs