Zaw Aung's Blog

Data bench, the same analytics job in six engines

Data bench asks how much the language matters for a typical data-analytics job. It runs the same workload in six different engines and shows the timings side by side.

The six engines

Engine How it’s built
Rust axum server, release build, parallel across all cores with rayon
JavaScript Node.js 22, typed arrays in shared memory, one worker thread per core
Python + pandas FastAPI, vectorised NumPy and pandas, one core
Python + Polars FastAPI, fully Polars-native including data generation, all cores
Python (pure) FastAPI, plain loops, one process per core over shared memory
JavaScript in the browser the same code, one Web Worker per core on your own device

The last one is the odd one out: it runs on the visitor’s machine instead of the server, which makes it a comparison between my VPS and whatever you are holding.

The workload

Every engine generates the identical dataset from the same pseudo-random generator (mulberry32), then does this:

Making the comparison honest

Benchmarks are easy to get wrong in a flattering direction, so two rules:

I also tried to be explicit about what each engine is allowed to use. pandas has no built-in parallelism, so it gets one core; Polars and Rust use all of them. If you want to compare at a fixed core count, each engine has a setting for that in the compose file.

How it is put together

browser ──► nginx (static page, reverse proxy)
              ├─ /api/rust/    ─► Rust service
              ├─ /api/python/  ─► FastAPI (pure, pandas, Polars)
              └─ /api/node/    ─► Node service

Four containers, each with its own job. Each service runs one benchmark at a time and replies 429 if it is busy, so a public page cannot be used to pile up work on the server, and the number of rows per request is capped so one visitor can’t request a run that exhausts memory.

A detail worth knowing

The browser lane uses shared memory between workers, which browsers allow only on pages that are cross-origin isolated. The page’s nginx config therefore sets the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers; without them the browser lane falls back to a single core.

Reading the results

Use the numbers for relative comparisons on one run, not as universal truths. The engines differ in more than language: Polars and pandas are libraries written mostly in compiled code, so “Python” being fast or slow here is partly a statement about its libraries, not just the interpreter.

Comments

Leave a comment

Comments are held for moderation before they appear.