Back to portfolioBack

WASM benchmark

Mandelbrot, 1024 x 1024

Not run yet. Choose Run.

Rust
JavaScript

Workloads

Loading the WebAssembly module.

1024 x 1024

  • Rust
    JavaScript
  • Rust
    JavaScript
  • Rust
    JavaScript
  • Rust
    JavaScript
  • Rust
    JavaScript

Bars inside a pair share a scale. Pairs do not, because the workloads differ by orders of magnitude. The whisker spans the 10th to 90th percentile of 30 samples.

Geometric mean of the speedups: needs a result where both sides ran and agreed.

Results as a table

No results yet.

Small work and strings

Cases where crossing into WebAssembly is large next to the work done: a million tiny calls, text copied in and out, and a sort of 100 numbers. Each row is worded like every other row.

  • Rust
    JavaScript
  • Rust
    JavaScript
  • Rust
    JavaScript
  • Rust
    JavaScript

Run this section to see, on your machine, when WebAssembly is worth reaching for.

Environment

Module
loading
Binary
Browser
Cores
Timer resolution
SIMD

What you are looking at

The same jobs, written once in Rust and once in JavaScript, timed on your machine just now. Different machines and browsers give different answers. Nothing on this page is a stored number: every figure was measured in this tab.

The pictures show what each job computes. Mandelbrot is an image filled in row by row, N-body is the final positions as points, matrix multiply is a heat map of the product, the prime sieve is the primes under 10,000 on an Ulam spiral, and sort is the array as a line before and after.

How it is measured

Each side warms up for 200 ms. Browsers round performance.now() to between 0.1 and 1 ms, so every sample is sized to last at least 20 ms and the time per call is its span divided by the calls inside it. Then 30 samples are taken, alternating the two sides so that drift from heat does not favour either. The bar is the median; the whisker is the 10th to 90th percentile.

Both sides get the same seeded input, and their outputs are compared before any verdict: exactly for integers, bytes and strings, and to a relative error of 1e-9 for floating point. If they differ the row says so and shows no verdict. Setup, such as making inputs, is outside the timed span for both.

Rust's times include copying data into WebAssembly memory and back out, because a JavaScript caller pays that cost. The JavaScript sort is the built-in typed-array sort, which is native code inside the browser. Mandelbrot, N-body, matrix multiply and the sieve are loops written for typed arrays with no allocation in the inner loop.

The visible race is separate from the timed run. It is untimed, it is cut into small pieces so it can draw, and it gives each lane equal processor time per turn so that progress reflects each engine's real speed. Its progress is for show and no number comes from it.

What it does not show

Startup cost beyond the module load time in the environment list, memory use, and anything that uses threads or SIMD. One browser on one machine is also one sample of the world.

Next Particles