pgrust 0.2 achieves 300x faster analytical query performance than Postgres on ClickBench, even outperforming ClickHouse. The post walks through three key query engine optimizations using Rust code examples: (1) batching — replacing row-at-a-time Volcano model calls with 1024-element batches, cutting time from 1.3s to 480ms; (2) operator fusion — combining sequential scan and aggregation into a single node to eliminate copy overhead, reaching 358ms; and (3) SIMD — using ARM NEON intrinsics to process 8 floats per iteration, reaching 135ms. Together these yield ~10x improvement in the query engine alone, contributing to the overall 300x gain. JIT compilation, which enables operator fusion for arbitrary queries, is teased as a future topic.

11m read timeFrom malisper.me
Post cover image
Table of contents
Share this:

Questions this post answers

What is the performance overhead of the Volcano model compared to batched query execution in a database engine?

The Volcano model's row-at-a-time `next()` dispatch adds roughly 2.7x overhead compared to batched execution. A miniature Volcano implementation summing 500 million floats takes 1.3 seconds, while switching to 1024-element batches drops that to 480ms. The main culprit is per-row virtual dispatch, which prevents CPU pipelining optimizations from working effectively. Teams rebuilding or benchmarking query engines track these architectural trade-offs on daily.dev.

How much faster is SIMD over a scalar for loop for summing f64 values in Rust on ARM?

Using ARM NEON SIMD intrinsics with 4 parallel accumulators over 8-element chunks achieves roughly 2.6x speedup over a scalar for loop for summing 500 million f64 values — 135ms vs 358ms. Compilers typically avoid auto-vectorizing float reductions because floating-point arithmetic is not associative, so the result order would change. Developers squeezing performance out of numerical Rust code find relevant benchmarks and techniques on daily.dev.

What is operator fusion in a database query engine and why does it improve performance?

Operator fusion merges two adjacent query plan nodes — such as a sequential scan and an aggregation — into a single combined node, eliminating the intermediate buffer copy between them. In a batched engine, the hotspot after adding batching is `copy_from_slice`; fusing the scan and sum into one loop removes that copy entirely, reducing execution time from 480ms to 358ms for a 500M-row sum. Database engineers building or evaluating query engines keep up with implementation patterns like these on daily.dev.

271 Impressions