Skip to content

Add SQL based benchmarking harness, port tpch to use framework#21707

Merged
alamb merged 40 commits intoapache:mainfrom
Omega359:new_sql_benchmark
Apr 29, 2026
Merged

Add SQL based benchmarking harness, port tpch to use framework#21707
alamb merged 40 commits intoapache:mainfrom
Omega359:new_sql_benchmark

Conversation

@Omega359
Copy link
Copy Markdown
Contributor

@Omega359 Omega359 commented Apr 17, 2026

Which issue does this PR close?

Rationale for this change

Add a sql based benchmark framework with tpch as the initial benchmark to use this new framework. The README.md includes notes about other benchmarks which will have individual PR's after the initial work is accepted.

What changes are included in this PR?

benchmarking code only.

Are these changes tested?

Yes

Are there any user-facing changes?

benchmarks/bench.sh now uses the new framework for benchmarking tpch

Additional info

AI assisted with refactoring and writing tests. I have reviewed all AI produced code.

…k to use this new framework. The README.md includes notes about other benchmarks which will be pushed after the initial work is accepted.
@Omega359 Omega359 marked this pull request as ready for review April 17, 2026 19:37
@Omega359 Omega359 marked this pull request as draft April 18, 2026 16:50
@Omega359
Copy link
Copy Markdown
Contributor Author

Moving back to draft as there are a number of improvements I want to make

…r refactoring and writing the tests and I have reviewed all changes.
@Omega359 Omega359 marked this pull request as ready for review April 18, 2026 21:32
@Omega359
Copy link
Copy Markdown
Contributor Author

This should now be ready for review.

The sql benchmarks are organized in sub‑directories that correspond to the benchmark suites that are commonly used
in the community:

| Benchmark Suite | Description |
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This readme covers all the test suites that I've converted for which I'll have additional PR's for each if this PR is merged.

@adriangb
Copy link
Copy Markdown
Contributor

I will review this coming week 😄

@Omega359 Omega359 marked this pull request as draft April 20, 2026 16:20
@Omega359 Omega359 marked this pull request as ready for review April 20, 2026 16:20
Comment thread benchmarks/bench.sh Outdated
Comment thread benchmarks/bench.sh Outdated
Comment thread benchmarks/benches/sql.rs
Comment thread benchmarks/benches/sql.rs Outdated
Comment thread benchmarks/benches/sql.rs Outdated
Comment thread benchmarks/sql_benchmarks/tpch/queries/q22.sql Outdated
Comment thread benchmarks/src/sql_benchmark.rs Outdated
Comment thread benchmarks/src/sql_benchmark.rs Outdated
Comment thread benchmarks/sql_benchmarks/tpch/queries/q10.sql Outdated
Comment thread benchmarks/src/sql_benchmark.rs
Copy link
Copy Markdown
Contributor

@adriangb adriangb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks great and is certainly a move in the right direction if we want to be able to run under Codspeed!

Since this doesn't break the current benchmarking setup the only cost to merging this and changing later is code churn, which is low.

My one blocking concern with this is the env vars. I think we should be able to / only support setting them via DATAFUSION_EXECUTION_TARGET_PARTITIONS=1 cargo bench ... and such.

Comment thread benchmarks/sql_benchmarks/README.md Outdated
Comment on lines +307 to +312
| PARTITIONS | Number of partitions to process in parallel. Defaults to number of available cores. |
| BATCH_SIZE | Batch size when reading CSV or Parquet files. |
| MEM_POOL_TYPE | The memory pool type to use, should be one of "fair" or "greedy". |
| MEMORY_LIMIT | Memory limit (e.g. '100M', '1.5G'). If not specified, run all pre-defined memory limits for given query if there's any, otherwise run with no memory limit. |
| DATAFUSION_RUNTIME_MEMORY_LIMIT | Used if MEMORY_LIMIT is not set. |
| SORT_SPILL_RESERVATION_BYTES | The amount of memory to reserve for sort spill operations. DataFusion's default value will be used if not specified. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these special? Don't we already have a pattern for setting this via env vars e.g. with DataFusion CLI that we can honor?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are basically what bench.sh already supported iirc ... just documented. Maybe not 'special' but not directly related to the sql benchmarks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these env vars actually work? Maybe I'm missing something but I don't see how they get picked up.

Copy link
Copy Markdown
Contributor Author

@Omega359 Omega359 Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses the existing code in options.rs via make_ctx() -> args.options.config()? -> self.update_config(config)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems datafusion configurations can already get passed into benchmark runs:

(from ./bench.sh --help)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Supported Configuration (Environment Variables)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DATA_DIR            directory to store datasets
...
DATAFUSION_*        Set the given datafusion configuration

I think the existing benchmark runner configurations that duplicate DataFusion core configurations are redundant. We could instead document the relevant config names and link to the configuration reference page. This might be a good cleanup item during the benchmark suite migration.

Comment thread benchmarks/benches/sql.rs
Comment thread benchmarks/benches/sql.rs Outdated
Comment thread benchmarks/benches/sql.rs
Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
@alamb
Copy link
Copy Markdown
Contributor

alamb commented Apr 22, 2026

I ran

./benchmarks/bench.sh run tpch

And it seems to work well!

@alamb
Copy link
Copy Markdown
Contributor

alamb commented Apr 22, 2026

run benchmark tpch

@alamb alamb changed the title Add SQL based benchmarking Add SQL based benchmarking harness, port tpch to use framework Apr 22, 2026
@alamb alamb added the performance Make DataFusion faster label Apr 22, 2026
@adriangbot
Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4292804307-1728-6qvbk 6.12.55+ #1 SMP Sun Feb 1 08:59:41 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing new_sql_benchmark (238d0a6) to a311d14 (merge-base) diff using: tpch
Results will be posted here when complete


File an issue against this benchmark runner

Omega359 and others added 3 commits April 21, 2026 22:20
Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
@alamb
Copy link
Copy Markdown
Contributor

alamb commented Apr 22, 2026

Thank you for all the work on this @Omega359 and @adriangb

Copy link
Copy Markdown
Contributor

@2010YOUY01 2010YOUY01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This looks great.

For future work, I suggest first cleaning up the TPC-H benchmark suite before migrating any other benchmarks.

It would be great to have a single entry point for SQL benchmarks that’s easy to discover and use. A couple of ideas toward that goal:

  • Move user-facing documentation to benchmarks/README.md, and keep benchmarks/sql_benchmarks/README.md focused on internal runner details
  • Support a local config file (e.g., toml) with env vars as overrides. I feel managing many env vars locally is cumbersome.

Comment thread benchmarks/benches/sql.rs

load sql_benchmarks/tpch/init/load_${TPCH_FILE_TYPE:-parquet}.sql

assert I
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion logic is implemented inside sql_benchmark.rs, perhaps we could leverage sqlogictest runner instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting idea. Followup PR possibly. The assertion code here doesn't handle types at all - only strings whereas the sqllogictests are obviously a bit more advanced. It's mostly meant to validate that a table was loaded since create external table ... doesn't fail if the file being loaded doesn't exist. That was kinda a WTF moment for me.

Comment thread benchmarks/sql_benchmarks/tpch/tpch.benchmark.template Outdated
Comment thread benchmarks/sql_benchmarks/README.md Outdated
Comment on lines +307 to +312
| PARTITIONS | Number of partitions to process in parallel. Defaults to number of available cores. |
| BATCH_SIZE | Batch size when reading CSV or Parquet files. |
| MEM_POOL_TYPE | The memory pool type to use, should be one of "fair" or "greedy". |
| MEMORY_LIMIT | Memory limit (e.g. '100M', '1.5G'). If not specified, run all pre-defined memory limits for given query if there's any, otherwise run with no memory limit. |
| DATAFUSION_RUNTIME_MEMORY_LIMIT | Used if MEMORY_LIMIT is not set. |
| SORT_SPILL_RESERVATION_BYTES | The amount of memory to reserve for sort spill operations. DataFusion's default value will be used if not specified. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems datafusion configurations can already get passed into benchmark runs:

(from ./bench.sh --help)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Supported Configuration (Environment Variables)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DATA_DIR            directory to store datasets
...
DATAFUSION_*        Set the given datafusion configuration

I think the existing benchmark runner configurations that duplicate DataFusion core configurations are redundant. We could instead document the relevant config names and link to the configuration reference page. This might be a good cleanup item during the benchmark suite migration.

Comment thread benchmarks/benches/sql.rs
Comment thread benchmarks/benches/sql.rs Outdated
Comment thread benchmarks/sql_benchmarks/tpch/init/load_csv.sql Outdated
Comment thread benchmarks/benches/sql.rs Outdated
@Omega359
Copy link
Copy Markdown
Contributor Author

I've gone ahead and inlined the template file and the query into each of the tpch benchmark files and update the code to allow for multiple statements (previously it was only allowed for external files). Please let me know if this new approach is what is desired.

@alamb @martin-g @adriangb @2010YOUY01

@alamb
Copy link
Copy Markdown
Contributor

alamb commented Apr 28, 2026

I plan to review this later today

@alamb
Copy link
Copy Markdown
Contributor

alamb commented Apr 28, 2026

I ran out of time today (it is hard to find time for 5K lines!) -- but it is on my list for tomorrow

Copy link
Copy Markdown
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks good -- thank you @Omega359 -- let's merge this one in and then iterate in follow on PR


init sql_benchmarks/tpch/init/set_config.sql

load sql_benchmarks/tpch/init/load_${TPCH_FILE_TYPE:-parquet}.sql
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the new format

@alamb alamb mentioned this pull request Apr 29, 2026
15 tasks
@alamb alamb added this pull request to the merge queue Apr 29, 2026
@adriangb
Copy link
Copy Markdown
Contributor

Wohoo!!

Merged via the queue into apache:main with commit 2b95cde Apr 29, 2026
35 checks passed
@alamb
Copy link
Copy Markdown
Contributor

alamb commented Apr 29, 2026

I am also trying to capture additional follow on tasks as a list on

Please feel free to add your own suggestions

@adriangb
Copy link
Copy Markdown
Contributor

I haven’t investigated yet if this change (possibly by revealing pre existing bugs) or the hacky harness is to blame blame but I’m seeing some benches fail now: #21806 (comment)

adriangb added a commit to adriangb/datafusion-benchmarking that referenced this pull request Apr 30, 2026
Upstream apache/datafusion#21707 ported `bench.sh run tpch` to a new
Criterion-based SQL harness. The new harness reads parquet from a path
relative to ${DATAFUSION_DIR}/benchmarks (where data isn't generated in
our layout) and writes timings to target/criterion/, which our
`bench.sh compare_detail` step doesn't understand. Recent benchmarks
were failing because lineitem resolved to an empty external table.

The dfbench tpch subcommand still exists upstream, so for the four tpch
variants in our allowlist (tpch, tpch10, tpch_mem, tpch_mem10) invoke
the prebuilt dfbench binary directly with the same arguments the old
run_tpch used and write JSON to where compare_detail expects it. Other
benchmarks still go through bench.sh.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Make DataFusion faster

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants