By Evan Miller
May 7, 2013
My friend Adrian Holovaty has responded to one of the comments I made in “Why I Develop For The Mac”. In that piece, I remarked that HTML5
<canvas> is slow. Adrian argued that his Soundslice program, which uses
<canvas> extensively, achieves excellent real-time graphics performance, although some hacks were required along the way.
I don't disagree, but I thought I'd clarify what I meant when I said
<canvas> was slow.
My desktop apps typically need to draw thousands of shapes, say, a map of U.S. counties (over 3,000 irregular shapes), or a scatterplot with tens of thousands of small circles. Today's web browsers just can't draw those quickly enough to feel like real-time interaction — even with the hacks that Adrian recommends. If you only need to draw a few dozen shapes at a time, like Soundslice does, then by all means, use a web canvas (or several).
It's a mistake, of course, to think that native code dispenses with the need for hacks. In the conclusion to Adrian's piece, a fictitious interlocutor representing the “Evan” point of view objects: “Well, if <canvas> is only fast if you use these various hacks, it's not really fast, then, is it?”
On the contrary, I think any programmer trying to push the limits of their hardware — desktop, mobile, console, you name it — will eventually need hacks. Apple has even documented the most popular graphics hacks in their Drawing Performance Guidelines, which I've found to be invaluable, albeit incomplete.
To give you an idea about the need for hacks on the desktop, take this innocent-looking scatterplot:
The goal: draw this quickly.
Seems simple enough, but there's a lot going on beneath the surface. Here's how my C routine draws it:
Divide up the data into sub-arrays — one per core
Allocate a black-and-white image for each core. (Full color is too expensive — it requires a separate computation for each color channel.)
Using threads, simultaneously draw a scatterplot into each image context using the Quartz API
Blend component images together into a final image
And that's just a fraction of the overall scatterplot routine — I have a special case for large numbers of points, a special case for large numbers of points that share the same coordinates, and a special case for points that reside exclusively on integer coordinates. The code is ugly, but each branch proved itself necessary at some point in development and testing.
But all that's part of what makes desktop development so much fun for me — it seems like there's almost always another layer of hacks available. It's like swimming in the deep end.
You're reading evanmiller.org, a random collection of math, tech, and musings. If you enjoyed this, you might also like: