Monday, 13 February 2012

drawCircle is slow

This is something I discovered at the weekend. I already knew that the drawCircle function of the Graphics class is slow, slow enough that you don't want to be using it to draw too many circles at once at runtime. Instead render them into a BitmapData using BitmapData.draw wherever possible.

I didn't realise how inefficient drawCircle is though until I captured a call stack while debugging, after changing the order in which a class was initialised, which gives an insight into how it renders a circle:

ArgumentError: Error #2004: One of the parameters is invalid.
at flash.display::Graphics/drawRoundRect()
at flash.display::Graphics/drawCircle()
at Game/DrawCurr()[/Users/JohnB/Flash/Rings/code/]
at Game/Tick()[/Users/JohnB/Flash/Rings/code/]

So instead of using a nice efficient algorithm to draw the circle in one go drawCircle is calling drawRoundRect, to presumably draw four separate elliptical corners and four straight edges. It doesn't need to draw the straight sections, but it has to do a lot of calculations to work that out from the drawRoundRect call. It may be 'quicker' just to draw them.

This has some interesting implications. For a theoretical performance boost it makes sense to call drawRoundRect directly, bypassing drawCircle altogether. Only in theory though, as the underlying drawing code is so slow that it's probably impossible to call it often enough in a frame for this optimisation to make a measurable difference.

More usefully this suggests that drawing ellipses is no slower than drawing circles. Circles should be faster to draw as only an eighth of the circle (an octant) needs to be drawn, compared to a quarter ellipse (quadrant), before being mirrored to draw the rest. But if both use the same underlying algorithm then circles will be no faster, and there's no need to prefer them in drawing code.

But, as will surprise no-one who had used it, the main conclusion is: drawCircle is slow.

No comments:

Post a Comment