Member-only story
A Poor Man’s Web Worker
How an experimental technology can save the day

For a while now, I’ve been developing a browser-based Earth mapping system using JavaScript and HTML canvas. One of the key challenges of this work has been keeping the user interface responsive while projecting 3D latitudes/longitudes onto a 2D canvas. Every point of every feature on the map must be transformed using this trigonometry:
x = R cosΦ sin(λ - λ₀)
y = R (cosΦ₀ sinΦ - sinΦ₀ cosΦ cos(λ - λ₀))
To appreciate the scale of this problem, a typical map may comprise dozens of layers, with each layer having hundreds of features, and with each feature comprising thousands of points.
All of these points must be run through that projection formula any time the user pans or zooms. Furthermore, because the user can freely reposition the point of observation, no meaningful caching scheme can be employed.
I always thought that there would come a time when shifting that math to a separate thread would be necessary, so I’ve kept my eye on the promise of web workers.
Recently, I’ve been implementing a collision detection system to recognize and correct overlapping map labels. The computations necessary to do this go way beyond what’s acceptable to the user. This was the project’s tipping point — it was time to look seriously at implementing a web worker.
Sadly, the results of that effort were disappointing.
The mechanics of web workers are simple enough. Any of the online tutorials are sufficient to get us started. Just to review, the promise of web workers is that the browser’s main thread can be kept free to respond to mouse and keyboard events, while the web worker thread can be fully dedicated to computations.
Unfortunately, there’s a major drawback with the way this works: the postMessage
function must be used to shuttle inputs and outputs back and forth. The toy examples that are demonstrated in tutorials often brush this off as a simple implementation detail, when in practice it becomes a major bottleneck.
In Optimizing Performance with Web Workers, Yi Chen documented this problem, noting “serialization/deserialization of 4000 objects took around 20 ~ 30ms and canceled out the…