Mandelbrot set computed in WebAssembly


About the code

This example shows how to call a function compiled in WA (WebAssembly) from Python. It also shows how to make a page interactive by binding Python functions to GUI elements and a canvas element.

The mandelbrot.wasm file provides a few functions written in C and compiled to WebAssembly:

  • float mandelbrot_point(const float x0,const float y0, const unsigned short n_steps);
  • unsigned int mandelbrot(const float x0, const float y0, const float x1, const float y1, const unsigned int nxy, const unsigned int n_steps, float *out);
  • float scale_to_1(float *data, unsigned int n_data);
  • int cmap_grayscale(float max_val, float *data, unsigned int n_data, unsigned char *pixels);

The first of them (mandelbrot_point()) tests the Mandelbrot criterion at \(x_0, y_0\) i.e. whether \(|z_n| < 2\) for the sequence of complex numbers \(z_n = z_{n-1}^2 + (x_0 + y_0 i)\) and is not used by the Python code. It returns the number of iterations it took to escape the assumed radius (which is 2.0).

The second function calls mandelbrot_point() for nxy*nxy points to compute a square fragment of a fractal. It returns the number of points tested which is also the number of values stored in the given data buffer float *out. The third one takes a buffer of float numbers and re-scales them so the are in the range [0,1] and that is just for coloring. Finally, the fourth function takes a buffer of float numbers and converts them to RGBA bytes that will be used to color pixels.

All these functions can be accessed from the wasm module as mandelbrot_instance.exports.FNAME where FNAME if the function name, e.g. mandelbrot_instance.exports.mandelbrot() or mandelbrot_instance.exports.cmap_grayscale().

The most challenging part of this project is the memory management, which is done in Python. The run_mandelbrot() function creates a new memory buffer and attaches it to a new instance of a mandelbrot module. Then it grows the buffer to 50 pages, 16KB each. The buffer doesn’t grow automatically and it’s programmer responsibility to adjust its size properly.