Skip to content

Commit 3fcb504

Browse files
committed
docs: update all benchmarks with hash table keyword lookup results
15-27% faster across all operations. Now 4x faster than libpg_query (was 3x), 27x faster than sqlparser-rs (was 21x).
1 parent 7f53668 commit 3fcb504

3 files changed

Lines changed: 74 additions & 74 deletions

File tree

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@ All operations run in sub-microsecond latency on modern hardware:
88

99
| Operation | Latency | Notes |
1010
|---|---|---|
11-
| Classify statement (BEGIN) | **36 ns** | Tier 2: type + metadata only |
12-
| Parse SET statement | **130 ns** | Full AST |
13-
| Parse simple SELECT | **223 ns** | Full AST |
14-
| Parse complex SELECT (JOINs, GROUP BY, HAVING) | **1.4 µs** | Full AST |
15-
| Parse INSERT | **244 ns** | Full AST |
16-
| Query reconstruction (round-trip) | **132-263 ns** | Parse → emit |
17-
| Arena reset | **3.6 ns** | O(1) pointer rewind |
11+
| Classify statement (BEGIN) | **29 ns** | Tier 2: type + metadata only |
12+
| Parse SET statement | **111 ns** | Full AST |
13+
| Parse simple SELECT | **186 ns** | Full AST |
14+
| Parse complex SELECT (JOINs, GROUP BY, HAVING) | **1.1 µs** | Full AST |
15+
| Parse INSERT | **212 ns** | Full AST |
16+
| Query reconstruction (round-trip) | **116-226 ns** | Parse → emit |
17+
| Arena reset | **3.5 ns** | O(1) pointer rewind |
1818

1919
Compared to other parsers on the same queries:
2020

2121
| Parser | Simple SELECT | Complex SELECT | Notes |
2222
|---|---|---|---|
23-
| **ParserSQL** | **223 ns** | **1,189 ns** | This project |
24-
| libpg_query (raw parse) | 684 ns (3.1x slower) | 3,304 ns (2.8x) | PostgreSQL's own parser |
25-
| sqlparser-rs (Rust) | 4,687 ns (21x slower) | 23,411 ns (19x) | Apache DataFusion |
23+
| **ParserSQL** | **175 ns** | **975 ns** | This project |
24+
| libpg_query (raw parse) | 718 ns (4.1x slower) | 3,479 ns (3.6x) | PostgreSQL's own parser |
25+
| sqlparser-rs (Rust) | 4,687 ns (27x slower) | 23,411 ns (24x) | Apache DataFusion |
2626

2727
See [docs/benchmarks/](docs/benchmarks/) for full results and [REPRODUCING.md](docs/benchmarks/REPRODUCING.md) for reproduction instructions.
2828

docs/benchmarks/comparison.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,31 @@
2222

2323
| Query | ParserSQL | pg_query raw | pg_query +JSON | sqlparser-rs |
2424
|---|---|---|---|---|
25-
| `SELECT col FROM t WHERE id = 1` | **223 ns** | 684 ns | 1,872 ns | 4,687 ns |
26-
| `SELECT ... JOIN ... WHERE` | **579 ns** | 1,646 ns | 4,509 ns | 10,684 ns |
27-
| `SELECT ... GROUP BY ... HAVING ... ORDER BY ... LIMIT` | **1,189 ns** | 3,304 ns | 8,675 ns | 23,411 ns |
28-
| `INSERT INTO t (cols) VALUES (...)` | **244 ns** | 781 ns | 1,831 ns | 3,784 ns |
29-
| `UPDATE t SET ... WHERE` | **236 ns** | 1,907 ns | | 4,102 ns |
30-
| `DELETE FROM t WHERE` | **181 ns** | 1,373 ns | | 3,049 ns |
31-
| `BEGIN` | **36 ns** | 230 ns | 421 ns | 412 ns |
25+
| `SELECT col FROM t WHERE id = 1` | **175 ns** | 718 ns | 2,018 ns | 4,687 ns |
26+
| `SELECT ... JOIN ... WHERE` | **440 ns** | 1,745 ns | 4,804 ns | 10,684 ns |
27+
| `SELECT ... GROUP BY ... HAVING ... ORDER BY ... LIMIT` | **975 ns** | 3,479 ns | 9,082 ns | 23,411 ns |
28+
| `INSERT INTO t (cols) VALUES (...)` | **212 ns** | 849 ns | 1,933 ns | 3,784 ns |
29+
| `UPDATE t SET ... WHERE` | **214 ns** | | 2,075 ns | 4,102 ns |
30+
| `DELETE FROM t WHERE` | **149 ns** | | 1,512 ns | 3,049 ns |
31+
| `BEGIN` | **29 ns** | 259 ns | 441 ns | 412 ns |
3232

3333
### Speedup ratios
3434

3535
| Query | vs pg_query (raw parse) | vs pg_query (+JSON) | vs sqlparser-rs |
3636
|---|---|---|---|
37-
| SELECT simple | **3.1x** | 8.4x | **21x** |
38-
| SELECT JOIN | **2.8x** | 7.8x | **18x** |
39-
| SELECT complex | **2.8x** | 7.3x | **19x** |
40-
| INSERT | **3.2x** | 7.5x | **16x** |
41-
| BEGIN | **6.4x** | 11.7x | **11x** |
37+
| SELECT simple | **4.1x** | 11.5x | **27x** |
38+
| SELECT JOIN | **4.0x** | 10.9x | **24x** |
39+
| SELECT complex | **3.6x** | 9.3x | **24x** |
40+
| INSERT | **4.0x** | 9.1x | **18x** |
41+
| BEGIN | **8.9x** | 15.2x | **14x** |
4242

4343
---
4444

4545
## Analysis
4646

4747
### vs libpg_query (fair comparison: raw parse only)
4848

49-
**ParserSQL is ~3x faster** than PostgreSQL's own parser when comparing parse-only (no JSON serialization). This is a genuine speedup from:
49+
**ParserSQL is ~4x faster** than PostgreSQL's own parser when comparing parse-only (no JSON serialization). This is a genuine speedup from:
5050

5151
1. **Arena allocation** — our parser allocates AST nodes from a bump allocator (3.5ns reset). PostgreSQL uses its MemoryContext system which is more general but has higher per-allocation overhead.
5252
2. **Zero-copy strings** — our `StringRef` points into the original input. PostgreSQL copies identifier strings into palloc'd memory.
@@ -56,16 +56,16 @@ Note: libpg_query's raw parse still includes PostgreSQL memory context setup/tea
5656

5757
### vs libpg_query (full: parse + JSON serialize)
5858

59-
The **7-8x** ratio includes JSON serialization overhead in libpg_query. This is how `pg_query_parse()` is typically used, but it's not a fair parse-only comparison.
59+
The **9-15x** ratio includes JSON serialization overhead in libpg_query. This is how `pg_query_parse()` is typically used, but it's not a fair parse-only comparison.
6060

6161
### vs sqlparser-rs
6262

63-
**ParserSQL is 11-21x faster**. This is the fairest comparison — both are standalone syntax parsers. The speed gap comes from:
63+
**ParserSQL is 14-27x faster**. This is the fairest comparison — both are standalone syntax parsers. The speed gap comes from:
6464

6565
1. **Arena vs heap** — sqlparser-rs uses `Box<Expr>`, `Vec<SelectItem>`, etc. Each allocation goes through Rust's allocator.
6666
2. **Zero-copy vs owned strings** — sqlparser-rs creates `String` values. We use `StringRef` pointing into input.
6767
3. **32-byte nodes vs enum variants** — Rust's richly-typed AST enums carry more data per node.
68-
4. **Binary search keyword lookup**fast path for the tokenizer.
68+
4. **Hash table keyword lookup**O(1) FNV-1a hash vs tokenizer construction in sqlparser-rs.
6969

7070
---
7171

docs/benchmarks/latest.md

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# SQL Parser Performance Report
22

3-
**Date:** 2026-03-24 17:56 UTC
3+
**Date:** 2026-03-24 21:48 UTC
44
**Host:** ci-big6-202511.vm
55
**CPU:** AMD Ryzen 9 5950X 16-Core Processor
66
**OS:** Linux 6.17.0-14-generic
77
**Compiler:** g++ (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
8-
**Git:** main @ f97f966
8+
**Git:** main @ 7f53668
99
**Unit tests:** 430 passing
1010

1111
---
@@ -14,66 +14,66 @@
1414

1515
| Operation | Latency | Target | Status |
1616
|---|---|---|---|
17-
| BM_Classify_Insert | 209 ns | <500ns | MET |
18-
| BM_Classify_Update | 240 ns | <500ns | MET |
19-
| BM_Classify_Delete | 184 ns | <500ns | MET |
20-
| BM_Classify_Begin | 35.9 ns | <100ns | MET |
21-
| BM_Set_Simple | 129 ns | <300ns | MET |
22-
| BM_Set_Names | 131 ns | <300ns | MET |
23-
| BM_Set_MultiVar | 257 ns | <300ns | MET |
24-
| BM_Set_FunctionRHS | 215 ns | <300ns | MET |
25-
| BM_Select_Simple | 217 ns | <500ns | MET |
26-
| BM_Select_MultiColumn | 462 ns | <500ns | MET |
27-
| BM_Select_Join | 591 ns | <2us | MET |
28-
| BM_Select_Complex | 1403 ns | <2us | MET |
29-
| BM_Select_MultiJoin | 1452 ns | <2us | MET |
30-
| BM_Emit_SetSimple | 131 ns | <500ns | MET |
31-
| BM_Emit_SelectSimple | 263 ns | <500ns | MET |
32-
| BM_ArenaReset | 3.55 ns | <10ns | MET |
33-
| BM_PgSQL_Select_Simple | 220 ns |||
34-
| BM_PgSQL_Set_Simple | 96.9 ns |||
35-
| BM_MT_Set_Simple/threads:1 | 124 ns |||
36-
| BM_MT_Set_Simple/threads:2 | 129 ns |||
37-
| BM_MT_Set_Simple/threads:4 | 134 ns |||
38-
| BM_MT_Set_Simple/threads:8 | 138 ns |||
39-
| BM_MT_Select_Simple/threads:1 | 215 ns |||
40-
| BM_MT_Select_Simple/threads:2 | 225 ns |||
41-
| BM_MT_Select_Simple/threads:4 | 231 ns |||
42-
| BM_MT_Select_Simple/threads:8 | 246 ns |||
43-
| BM_MT_Select_Complex/threads:1 | 1401 ns |||
44-
| BM_MT_Select_Complex/threads:2 | 1403 ns |||
45-
| BM_MT_Select_Complex/threads:4 | 1459 ns |||
46-
| BM_MT_Select_Complex/threads:8 | 1509 ns |||
47-
| BM_MT_Classify_Begin/threads:1 | 35.8 ns |||
48-
| BM_MT_Classify_Begin/threads:2 | 36.7 ns |||
49-
| BM_MT_Classify_Begin/threads:4 | 37.5 ns |||
50-
| BM_MT_Classify_Begin/threads:8 | 38.2 ns |||
51-
| BM_Percentile_Set_Simple | 909 ns |||
52-
| BM_Percentile_Select_Simple | 1008 ns |||
53-
| BM_Percentile_Select_Complex | 2076 ns |||
54-
| BM_Percentile_Classify_Begin | 813 ns |||
17+
| BM_Classify_Insert | 192 ns | <500ns | MET |
18+
| BM_Classify_Update | 195 ns | <500ns | MET |
19+
| BM_Classify_Delete | 147 ns | <500ns | MET |
20+
| BM_Classify_Begin | 29.0 ns | <100ns | MET |
21+
| BM_Set_Simple | 114 ns | <300ns | MET |
22+
| BM_Set_Names | 109 ns | <300ns | MET |
23+
| BM_Set_MultiVar | 240 ns | <300ns | MET |
24+
| BM_Set_FunctionRHS | 174 ns | <300ns | MET |
25+
| BM_Select_Simple | 186 ns | <500ns | MET |
26+
| BM_Select_MultiColumn | 355 ns | <500ns | MET |
27+
| BM_Select_Join | 426 ns | <2us | MET |
28+
| BM_Select_Complex | 1063 ns | <2us | MET |
29+
| BM_Select_MultiJoin | 1046 ns | <2us | MET |
30+
| BM_Emit_SetSimple | 116 ns | <500ns | MET |
31+
| BM_Emit_SelectSimple | 242 ns | <500ns | MET |
32+
| BM_ArenaReset | 3.80 ns | <10ns | MET |
33+
| BM_PgSQL_Select_Simple | 177 ns |||
34+
| BM_PgSQL_Set_Simple | 88.9 ns |||
35+
| BM_MT_Set_Simple/threads:1 | 113 ns |||
36+
| BM_MT_Set_Simple/threads:2 | 113 ns |||
37+
| BM_MT_Set_Simple/threads:4 | 115 ns |||
38+
| BM_MT_Set_Simple/threads:8 | 121 ns |||
39+
| BM_MT_Select_Simple/threads:1 | 174 ns |||
40+
| BM_MT_Select_Simple/threads:2 | 223 ns |||
41+
| BM_MT_Select_Simple/threads:4 | 198 ns |||
42+
| BM_MT_Select_Simple/threads:8 | 204 ns |||
43+
| BM_MT_Select_Complex/threads:1 | 1042 ns |||
44+
| BM_MT_Select_Complex/threads:2 | 1049 ns |||
45+
| BM_MT_Select_Complex/threads:4 | 1093 ns |||
46+
| BM_MT_Select_Complex/threads:8 | 1192 ns |||
47+
| BM_MT_Classify_Begin/threads:1 | 29.5 ns |||
48+
| BM_MT_Classify_Begin/threads:2 | 29.3 ns |||
49+
| BM_MT_Classify_Begin/threads:4 | 29.7 ns |||
50+
| BM_MT_Classify_Begin/threads:8 | 32.0 ns |||
51+
| BM_Percentile_Set_Simple | 915 ns |||
52+
| BM_Percentile_Select_Simple | 965 ns |||
53+
| BM_Percentile_Select_Complex | 1722 ns |||
54+
| BM_Percentile_Classify_Begin | 807 ns |||
5555

5656
---
5757

5858
## Multi-Threaded Scaling (per-thread latency)
5959

6060
| Operation | 1 thread | 2 threads | 4 threads | 8 threads |
6161
|---|---|---|---|---|
62-
| BM_MT_Set_Simple | 124ns | 129ns | 134ns | 138ns |
63-
| BM_MT_Select_Simple | 215ns | 225ns | 231ns | 246ns |
64-
| BM_MT_Select_Complex | 1401ns | 1403ns | 1459ns | 1509ns |
65-
| BM_MT_Classify_Begin | 35.8ns | 36.7ns | 37.5ns | 38.2ns |
62+
| BM_MT_Set_Simple | 113ns | 113ns | 115ns | 121ns |
63+
| BM_MT_Select_Simple | 174ns | 223ns | 198ns | 204ns |
64+
| BM_MT_Select_Complex | 1042ns | 1049ns | 1093ns | 1192ns |
65+
| BM_MT_Classify_Begin | 29.5ns | 29.3ns | 29.7ns | 32.0ns |
6666

6767
---
6868

6969
## Percentile Latency
7070

7171
| Operation | avg | p50 | p95 | p99 | min | max |
7272
|---|---|---|---|---|---|---|
73-
| BM_Percentile_Set_Simple | 936.994ns | 932ns | 942ns | 952ns | 911ns | 39.593kns |
74-
| BM_Percentile_Select_Simple | 1.04875kns | 1.042kns | 1.052kns | 1.071kns | 1.021kns | 221.729kns |
75-
| BM_Percentile_Select_Complex | 2.14065kns | 2.124kns | 2.164kns | 2.184kns | 2.074kns | 25.176kns |
76-
| BM_Percentile_Classify_Begin | 833.356ns | 831ns | 842ns | 862ns | 811ns | 203.486kns |
73+
| BM_Percentile_Set_Simple | 948.284ns | 922ns | 1.052kns | 1.553kns | 871ns | 39.142kns |
74+
| BM_Percentile_Select_Simple | 1.00773kns | 992ns | 1.041kns | 1.362kns | 941ns | 62.395kns |
75+
| BM_Percentile_Select_Complex | 1.79424kns | 1.763kns | 1.803kns | 2.665kns | 1.723kns | 54.14kns |
76+
| BM_Percentile_Classify_Begin | 831.536ns | 821ns | 892ns | 1.082kns | 781ns | 60.311kns |
7777

7878
---
7979

0 commit comments

Comments
 (0)