Eleven years ago, I wrote a
somewhat new Web Workers
allowing me to make use of multiple cores and not tie up the UI thread
with the calculations.
Recently I decided to see how much I could improve it with
improvements to the web stack that have happened since then. The
result was much faster than what I’d managed previously:
The main improvements came from the use of typed
well as the memory savings compared to regular JS arrays that can
contain arbitrary values, it enabled the following improvements:
It’s possible for two arrays to share the same backing buffer, even
if they have different types. So while image data is exposed as
byte arrays with four entries per pixel (the RGBA components), we
can create a
uint32 array view of the same data with one entry
Array buffers can be transferred when posting messages to/from
workers. This basically lets us move blocks of memory between
threads rather than having to copy them.
It’s now possible to construct new
ImageData objects from
existing arrays. So we can use arrays transferred from workers as
image data directly, removing another set of copies.
I also switched the workers over to rendering 128x128 tiles rather
than single rows. This means the memory buffers don’t have to change
when the window is resized. In fact, I can allocate one buffer per
worker up front, and just transfer it back and forward to avoid more
It renders nice and fast on my 16 hyperthread desktop system, and also
performs decently on the Android devices I have.
Another improvement I added is a simple a toolbar to allow panning
around the image, zooming out as well as in, resetting the viewport
and switching to fullscreen.
I’ve published the code in a git repo here: