Benchmark Surface
Canonical local snapshot refreshed on April 22, 2026. This page keeps one stable PostgreSQL native-DSL report URL: tables and charts show the latest median refresh, while earlier snapshots are preserved in the narrative so history is not lost.
| Axis | Value |
|---|---|
| Drivers | qail-rs native Qail ASTs versus pgx SQL strings |
| Workloads | point, wide_rows, large_rows, many_params, aggregate |
| Modes | single, pipeline, pool10, latency |
| DB target | Local defaults on this page; both runners also accept DATABASE_URL or QAIL_BENCH_DATABASE_URL |
| Rounds | ROUNDS=2 on this page, ROUNDS=6 still recommended for publication-quality reruns |
| Harness | pg/examples/abba_qail_native_pgx.sh in the qail.rs workspace |
| qail-rs runner | pg/examples/qail_native_pgx_once.rs |
| pgx runner | pg/examples/pgx_native_benchmark.go |
| Sibling benchmark pages | This page stays the canonical qail-rs native-vs-pgx report; qail-zig vs pg.zig and ORM/SQLx comparisons remain on their own stable pages |
Native Throughput
Cells show pgx, qail-rs, then the qail-rs/pgx ratio. Higher is better.
| Workload | Single | Pipeline | Pool10 |
|---|---|---|---|
| Point lookup | pgx 35,028 qail-rs 41,820 1.19x | pgx 410,121 qail-rs 555,995 1.36x | pgx 107,278 qail-rs 169,501 1.58x |
| Wide rows | pgx 4,196 qail-rs 4,587 1.09x | pgx 3,903 qail-rs 5,388 1.38x | pgx 7,358 qail-rs 10,731 1.46x |
| Large rows | pgx 134 qail-rs 158 1.18x | pgx 142 qail-rs 175 1.23x | pgx 390 qail-rs 443 1.14x |
| Many params | pgx 23,066 qail-rs 26,434 1.15x | pgx 78,156 qail-rs 99,737 1.28x | pgx 89,286 qail-rs 128,905 1.44x |
| Aggregate | pgx 607 qail-rs 657 1.08x | pgx 719 qail-rs 851 1.18x | pgx 3,549 qail-rs 3,503 0.99x |
Latest April 22 median refresh: qail-rs wins 14 of 15 throughput cells. The exception is aggregate/pool10, where pgx is slightly ahead. Earlier March snapshots remain in this report as historical context.
Throughput — Pipeline Mode
Pipeline-mode queries per second. Higher is better.
| Workload | pgx | qail-rs | Ratio |
|---|---|---|---|
| Point lookup | 410K | 556K | 1.36× |
| Wide rows | 3.9K | 5.4K | 1.38× |
| Large rows | 142 | 175 | 1.23× |
| Many params | 78K | 100K | 1.28× |
| Aggregate | 719 | 851 | 1.18× |
Throughput — Pool10
Pool10-mode queries per second. Higher is better.
| Workload | pgx | qail-rs | Ratio |
|---|---|---|---|
| Point lookup | 107K | 170K | 1.58× |
| Wide rows | 7.4K | 11K | 1.46× |
| Large rows | 390 | 443 | 1.14× |
| Many params | 89K | 129K | 1.44× |
| Aggregate | 3.5K | 3.5K | 0.99× |
Latency Snapshot
Lower is better. The table shows p50 and p99 in milliseconds for the single-query latency mode.
| Workload | p50 | p99 |
|---|---|---|
| Point lookup | pgx 0.026 ms qail-rs 0.024 ms -10.03% | pgx 0.078 ms qail-rs 0.043 ms -45.24% |
| Wide rows | pgx 0.285 ms qail-rs 0.217 ms -23.71% | pgx 0.757 ms qail-rs 0.547 ms -27.76% |
| Large rows | pgx 7.791 ms qail-rs 6.530 ms -16.18% | pgx 9.324 ms qail-rs 8.060 ms -13.55% |
| Many params | pgx 0.040 ms qail-rs 0.035 ms -11.68% | pgx 0.107 ms qail-rs 0.118 ms +10.64% |
| Aggregate | pgx 1.826 ms qail-rs 1.771 ms -3.01% | pgx 3.048 ms qail-rs 2.869 ms -5.88% |
Latest April 22 latency refresh: qail-rs is lower on all five p50 slices and four of five p99 slices. The only negative tail case in this run is many_params, where pgx keeps a tighter p99.
Latency — p99
p99 latency in milliseconds. Lower is better.
Interpretation
This native matrix is the benchmark that matters for the public qail-rs story. qail-rs starts from native Qail ASTs here, while pgx continues to execute SQL strings. In the latest April 22 median refresh, qail-rs wins 14 of 15 throughput cells, all five p50 latency cells, and four of five p99 latency cells.
The strongest latest wins are where dispatch and execution-path overhead is exposed most clearly: 1.58x on point lookup pool10, 1.46x on wide_rows pool10, and 1.44x on many_params pool10. The main softness in this refresh is narrow: aggregate/pool10 is slightly negative on throughput, and many_params is the only p99 tail-latency loss.
Historical context still matters: prior March snapshots are retained in this report, but April 22 is now the live canonical read. The page keeps one stable URL and refreshes the tables/charts with new medians instead of creating a new benchmark page every run.
The earlier public Rust-vs-pgx page used the wrong surface for qail-rs by starting from raw SQL. That page measured protocol/runtime behavior only. This report supersedes it and should be treated as the canonical PostgreSQL benchmark page for qail-rs.
Revision Notes
- This report supersedes the earlier public Rust-vs-pgx page that measured qail-rs from raw SQL instead of native
QailASTs. - The qail-rs side now runs through
pg/examples/qail_native_pgx_once.rs, while pgx stays on SQL strings throughpg/examples/pgx_native_benchmark.go. - The aggregate workload now uses the dedicated four-column zero-copy receive path on qail-rs, and the hot query/pipeline paths reuse presized buffers more aggressively.
- April 22, 2026 is now the live canonical refresh on this page: latest tables and charts use the new two-round medians while prior March snapshots remain as context.
- The benchmark family stays split by surface for clarity and SEO: native
qail-rsvspgxhere,qail-zigvspg.zigon the Zig page, and ORM/SQLxcomparisons on their own report. - DB target selection remains env-driven via
DATABASE_URLorQAIL_BENCH_DATABASE_URL, so the same harness can be rerun against local or remote PostgreSQL.
Reproduce
Use local defaults, or set <code>DATABASE_URL</code> to point at a remote PostgreSQL instance.
git clone https://github.com/qail-io/qail.git
cd qail
DATABASE_URL='postgresql://user:pass@host:5432/db?sslmode=disable' \
RUNNERS='pgx qail_rs' \
ROUNDS=6 \
bash pg/examples/abba_qail_native_pgx.sh