Hey everyone ![]()
A 6-table join over 10 million rows in 0.7 ms. That’s 128× faster than Polars — and it’s running on hand-written Mojo kernels with zero CUDA anywhere in the stack.
I’ve been building MXFrame: a DataFrame query engine with a Polars-style lazy API, powered entirely by pre-compiled Mojo AOT kernels. One kernel source → PTX on NVIDIA, ROCm on AMD, Metal on Apple Silicon, all through DeviceContext.
Repo: GitHub - abhisheksreesaila/mxframe: GPU charged dataframe built using max framework · GitHub · Apache 2.0 · on PyPI
The idea
cuDF proved GPU DataFrames work — then welded the architecture to CUDA. Mojo cuts that cable.
So MXFrame is the cuDF architecture rebuilt on Mojo: a lazy logical plan with filter pushdown and join reordering, dispatching straight into AOT-compiled Mojo kernels over ctypes.
The design decision everything hangs on: compile once at build time, never at query time. Kernels ship as .so files, load in ~1 ms at process start, and every query after that is pure dispatch — no warmup, no JIT tax, no per-query compile. The only JIT left in the entire system is MAX Graph for GPU hash joins, compiled once per shape and cached for the session.
Results — all 22 TPC-H queries
RTX 3090 + AMD 12-core, warm median of 3, vs Polars and Pandas:
| 1M rows | 10M rows | |
|---|---|---|
| CPU path beats Polars | 21 / 22 | 18 / 22 |
| GPU path beats Polars | 16 / 22 | 15 / 22 |
The headliners at 10M rows:
- Q9 — 6-table join → 128×
- Q12 — join + agg → 89×
- Q7 — shipping volume → 42×
- Q8 — market share → 32×
All 22 verified correct against Polars output.
And the losses, because they matter more: Q4, Q6, Q13, Q21 still fall back to PyArrow compute and get beaten. That’s the next milestone, and it’s in the roadmap.
Every number above is reproducible on your own box — benchmark CSVs are committed in-repo, and official TPC-H data regenerates via DuckDB’s dbgen port:
pixi run python3 scripts/gen_tpch_parquet.py --sf 1
pixi run python3 scripts/bench_real_tpch.py --data-dir data/tpch_sf1 --runs 3
What Mojo and MAX made possible
- 93% of the codebase is Mojo — group aggs, masked aggs, inner + left hash joins, filter/gather, sort, unique. All hand-written.
- Writing a kernel once and getting PTX, ROCm, and Metal out of the same source still feels like cheating.
- AOT is the whole reason the small fast queries beat a Rust engine. When the query itself takes 0.7 ms, compile time isn’t overhead — it’s the entire race.
Video walkthrough
Architecture and benchmarks, if you’d rather watch than read:
Weekly Mojo/MAX kernel deep-dives on the channel → Mojo Monday AI
Stars, issues, and brutal benchmark scrutiny all welcome ![]()