Skip to content

perf: Coalesce batches before sorting in ExternalSorter to reduce merge fan-in - #21629

Closed
mbutrovich wants to merge 6 commits into
apache:mainfrom
mbutrovich:externalsorter
Closed

perf: Coalesce batches before sorting in ExternalSorter to reduce merge fan-in#21629
mbutrovich wants to merge 6 commits into
apache:mainfrom
mbutrovich:externalsorter

Conversation

@mbutrovich

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Partially addresses #21543. This is the ExternalSorter pipeline refactor from #21600, separated from the radix sort changes.

Rationale for this change

ExternalSorter's merge path sorts each incoming batch individually (typically 8192 rows), then k-way merges all of them. At scale (TPC-H SF10, ~60M rows in lineitem), this produces ~7300 individually-sorted batches feeding the k-way merge with high fan-in.

What changes are included in this PR?

Coalesce-then-sort pipeline

Replaces ExternalSorter's buffer-then-sort architecture with a coalesce-then-sort pipeline:

  • Incoming batches accumulate in a BatchCoalescer until sort_coalesce_target_rows (default 32768) is reached
  • Each coalesced batch is sorted and chunked back to batch_size, producing fewer, larger sorted runs
  • On memory pressure, sorted runs spill to disk (merged into one file when headroom is available, one file per run otherwise)
  • At query completion, runs are k-way merged via the existing StreamingMergeBuilder

This reduces merge fan-in from ~7300 to ~1800 runs at SF10, which is the primary source of speedup.

Spill strategy

  • With merge headroom (sort_spill_reservation_bytes > 0): merge all runs into a single sorted stream before spilling to one file. Fewer files = lower fan-in for the final MultiLevelMerge.
  • Without headroom (sort_spill_reservation_bytes == 0): spill each run as its own file. The multi-level merge handles low merge memory by reducing fan-in, so this no longer fails under tight memory budgets.

Dead code removal

Sorted runs no longer require an in-memory merge before spilling. Removes in_mem_sort_stream, sort_batch_stream, consume_and_spill_append, spill_finish, organize_stringview_arrays, and in_progress_spill_file.

Config changes

  • New: sort_coalesce_target_rows (default 32768)
  • Deprecated: sort_in_place_threshold_bytes (no longer read, warn attribute per API health policy)

Are these changes tested?

  • 4 new unit tests (coalescing, partial flush, per-run spill, merged spill)
  • All 48 sort unit tests pass
  • All sort fuzz, sort query fuzz, and spilling fuzz tests pass
  • information_schema.slt updated for new config

Are there any user-facing changes?

  • New config sort_coalesce_target_rows (default 32768) controls the coalesce target before sorting
  • sort_in_place_threshold_bytes is deprecated
  • The pipeline is more memory-efficient (shrinks reservations after sorting) so some workloads may spill less frequently
  • Sorts under tight memory budgets (sort_spill_reservation_bytes near zero) that previously failed now succeed via multi-level merge with reduced fan-in

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation core Core DataFusion crate sqllogictest SQL Logic Tests (.slt) common Related to common crate execution Related to the execution crate physical-plan Changes to the physical-plan crate labels Apr 14, 2026
///
/// Larger values reduce merge fan-in by producing fewer, larger
/// sorted runs.
pub sort_coalesce_target_rows: usize, default = 32768

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 wonder if we can make this somewhat adaptive: as we usually load everything in memory, it seems for very large sets larger batches would be even more favorable (e.g. use 10MiB "scratch space" for coalescing instead of 32KiB rows would make sense if our data is 1GiB and perhaps be even faster?)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Yeah I suspect we'd want to do a good sensitivity analysis on different types and batch sizes for lexsort_to_indices (and eventually the radix sort kernel). We might hit a point of diminishing returns/cache friendliness if our coalesced batches get too large.

This design also first spills from the sorted runs, so holding more unsorted rows in the coalescer may make it more likely for us to trigger spilling.

I'm definitely of the mind that we can and should tune this, but unclear what even a reasonable default right now would be. In Comet where we run TPC-H SF 1000, for example, I suspect we'll want longer sorted runs.

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

run benchmark tpch10

env:
PREFER_HASH_JOIN: false

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4246572576-1254-cr9dg 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 externalsorter (32a6882) to e6b32fe (merge-base) diff using: tpch10
Results will be posted here when complete


File an issue against this benchmark runner

@mbutrovich
mbutrovich marked this pull request as ready for review April 14, 2026 19:35
@mbutrovichmbutrovich added the performance Make DataFusion faster label Apr 14, 2026
@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

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
Details

Comparing HEAD and externalsorter
--------------------
Benchmark tpch_sf10.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ externalsorter ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1 │ 369.64 / 376.08 ±5.23 / 382.99 ms │ 369.46 / 374.50 ±3.39 / 378.57 ms │ no change │
│ QQuery 2 │ 485.14 / 497.33 ±11.38 / 515.80 ms │ 438.26 / 446.15 ±6.06 / 456.09 ms │ +1.11x faster │
│ QQuery 3 │ 589.99 / 660.25 ±37.61 / 696.76 ms │ 514.23 / 531.74 ±9.61 / 542.05 ms │ +1.24x faster │
│ QQuery 4 │ 407.91 / 473.96 ±36.86 / 509.58 ms │ 334.86 / 341.61 ±6.01 / 352.42 ms │ +1.39x faster │
│ QQuery 5 │ 1118.92 / 1156.54 ±22.75 / 1181.28 ms │ 1025.31 / 1066.24 ±22.28 / 1090.89 ms │ +1.08x faster │
│ QQuery 6 │ 133.59 / 136.32 ±2.93 / 141.42 ms │ 134.30 / 140.19 ±6.63 / 152.36 ms │ no change │
│ QQuery 7 │ 1563.72 / 1581.82 ±16.09 / 1609.94 ms │ 1361.03 / 1383.17 ±20.21 / 1417.51 ms │ +1.14x faster │
│ QQuery 8 │ 1471.30 / 1899.23 ±344.46 / 2196.56 ms │ 1160.48 / 1254.40 ±138.94 / 1530.54 ms │ +1.51x faster │
│ QQuery 9 │ 2125.14 / 2373.70 ±187.56 / 2699.90 ms │ 1781.61 / 1916.18 ±81.59 / 2024.46 ms │ +1.24x faster │
│ QQuery 10 │ 544.27 / 550.30 ±3.86 / 555.77 ms │ 495.92 / 510.99 ±10.93 / 524.00 ms │ +1.08x faster │
│ QQuery 11 │ 455.29 / 469.03 ±11.12 / 484.05 ms │ 426.61 / 433.24 ±5.62 / 442.76 ms │ +1.08x faster │
│ QQuery 12 │ 295.00 / 301.36 ±4.84 / 308.51 ms │ 279.36 / 282.79 ±2.83 / 286.06 ms │ +1.07x faster │
│ QQuery 13 │ 370.67 / 377.16 ±7.15 / 391.07 ms │ 344.14 / 353.84 ±5.61 / 360.05 ms │ +1.07x faster │
│ QQuery 14 │ 193.64 / 199.80 ±5.22 / 207.45 ms │ 191.75 / 199.09 ±6.65 / 209.34 ms │ no change │
│ QQuery 15 │ 322.12 / 329.85 ±6.15 / 339.31 ms │ 321.21 / 329.66 ±7.24 / 342.24 ms │ no change │
│ QQuery 16 │ 125.14 / 126.31 ±1.35 / 128.95 ms │ 113.56 / 122.03 ±8.02 / 136.95 ms │ no change │
│ QQuery 17 │ 1638.60 / 1875.12 ±120.43 / 1970.84 ms │ 1356.61 / 1406.75 ±36.24 / 1447.73 ms │ +1.33x faster │
│ QQuery 18 │ 1598.31 / 1648.45 ±45.52 / 1722.97 ms │ 1361.97 / 1443.48 ±55.54 / 1519.16 ms │ +1.14x faster │
│ QQuery 19 │ 274.77 / 289.38 ±25.56 / 340.35 ms │ 274.65 / 286.05 ±16.21 / 317.11 ms │ no change │
│ QQuery 20 │ 442.18 / 459.13 ±9.92 / 471.96 ms │ 429.72 / 448.05 ±11.89 / 466.01 ms │ no change │
│ QQuery 21 │ 3252.47 / 3363.47 ±59.18 / 3423.30 ms │ 2599.98 / 2658.02 ±30.81 / 2684.12 ms │ +1.27x faster │
│ QQuery 22 │ 186.83 / 197.41 ±7.15 / 208.14 ms │ 154.25 / 161.09 ±6.87 / 173.89 ms │ +1.23x faster │
└───────────┴────────────────────────────────────────┴────────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD) │ 19341.99ms │
│ Total Time (externalsorter) │ 16089.26ms │
│ Average Time (HEAD) │ 879.18ms │
│ Average Time (externalsorter) │ 731.33ms │
│ Queries Faster │ 15 │
│ Queries Slower │ 0 │
│ Queries with No Change │ 7 │
│ Queries with Failure │ 0 │
└───────────────────────────────┴────────────┘

Resource Usage

tpch10 — base (merge-base)

MetricValue
Wall time97.1s
Peak memory11.2 GiB
Avg memory8.6 GiB
CPU user884.8s
CPU sys75.7s
Peak spill0 B

tpch10 — branch

MetricValue
Wall time80.8s
Peak memory11.2 GiB
Avg memory7.8 GiB
CPU user795.9s
CPU sys68.9s
Peak spill0 B

File an issue against this benchmark runner

@Dandandan

Copy link
Copy Markdown
Contributor

Wooh, nice results

@Dandandan

Dandandan commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Lets compare to hash join (still 2x diff I think)

@Dandandan

Copy link
Copy Markdown
Contributor

run benchmark tpch10

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4246734700-1255-84ftb 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 externalsorter (32a6882) to e6b32fe (merge-base) diff using: tpch10
Results will be posted here when complete


File an issue against this benchmark runner

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

I also opened a new PR that scales our existing sort benchmark to larger numbers: #21630

In theory we should merge that first, then run the sort benchmark against main after that is in. In the meantime I can run that locally and update with results.

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

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
Details

Comparing HEAD and externalsorter
--------------------
Benchmark tpch_sf10.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ externalsorter ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ QQuery 1 │ 371.99 / 376.96 ±2.69 / 379.67 ms │ 373.11 / 374.56 ±0.99 / 376.21 ms │ no change │
│ QQuery 2 │ 136.84 / 139.64 ±2.41 / 142.60 ms │ 137.37 / 141.53 ±3.83 / 148.61 ms │ no change │
│ QQuery 3 │ 290.81 / 297.53 ±3.84 / 301.08 ms │ 294.21 / 297.24 ±2.49 / 301.82 ms │ no change │
│ QQuery 4 │ 157.06 / 158.25 ±1.04 / 160.18 ms │ 163.17 / 163.98 ±0.65 / 164.88 ms │ no change │
│ QQuery 5 │ 428.84 / 434.96 ±5.27 / 444.66 ms │ 451.75 / 457.04 ±4.95 / 464.64 ms │ 1.05x slower │
│ QQuery 6 │ 132.66 / 134.17 ±1.23 / 135.89 ms │ 133.50 / 134.61 ±0.86 / 135.48 ms │ no change │
│ QQuery 7 │ 563.02 / 587.09 ±15.45 / 606.59 ms │ 587.86 / 594.62 ±4.33 / 599.57 ms │ no change │
│ QQuery 8 │ 483.62 / 492.86 ±7.21 / 503.79 ms │ 478.84 / 491.04 ±9.87 / 506.50 ms │ no change │
│ QQuery 9 │ 707.85 / 714.91 ±6.70 / 724.34 ms │ 669.57 / 691.14 ±14.47 / 708.41 ms │ no change │
│ QQuery 10 │ 333.70 / 347.25 ±7.06 / 354.05 ms │ 340.97 / 354.39 ±10.48 / 368.41 ms │ no change │
│ QQuery 11 │ 104.30 / 112.04 ±5.42 / 119.20 ms │ 110.99 / 115.85 ±3.85 / 122.81 ms │ no change │
│ QQuery 12 │ 202.29 / 204.71 ±2.28 / 208.32 ms │ 208.39 / 209.76 ±1.29 / 212.04 ms │ no change │
│ QQuery 13 │ 305.63 / 319.39 ±7.94 / 328.85 ms │ 309.99 / 315.73 ±6.53 / 327.63 ms │ no change │
│ QQuery 14 │ 180.75 / 182.10 ±0.99 / 183.64 ms │ 181.13 / 182.52 ±1.44 / 185.24 ms │ no change │
│ QQuery 15 │ 338.13 / 342.58 ±2.38 / 345.31 ms │ 331.27 / 333.51 ±2.16 / 337.52 ms │ no change │
│ QQuery 16 │ 88.02 / 90.32 ±1.74 / 92.47 ms │ 84.29 / 86.72 ±2.30 / 89.96 ms │ no change │
│ QQuery 17 │ 771.91 / 803.56 ±18.47 / 824.96 ms │ 762.20 / 794.23 ±16.25 / 806.51 ms │ no change │
│ QQuery 18 │ 863.78 / 873.82 ±11.69 / 895.72 ms │ 869.91 / 920.79 ±38.92 / 970.84 ms │ 1.05x slower │
│ QQuery 19 │ 266.58 / 269.95 ±3.31 / 276.21 ms │ 272.78 / 279.70 ±6.65 / 288.50 ms │ no change │
│ QQuery 20 │ 320.19 / 327.34 ±5.56 / 335.30 ms │ 333.41 / 339.49 ±5.65 / 348.05 ms │ no change │
│ QQuery 21 │ 869.13 / 876.28 ±5.06 / 882.58 ms │ 848.74 / 859.56 ±14.49 / 887.53 ms │ no change │
│ QQuery 22 │ 78.97 / 81.54 ±2.08 / 85.14 ms │ 82.82 / 85.25 ±2.54 / 88.65 ms │ no change │
└───────────┴────────────────────────────────────┴────────────────────────────────────┴──────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD) │ 8167.27ms │
│ Total Time (externalsorter) │ 8223.26ms │
│ Average Time (HEAD) │ 371.24ms │
│ Average Time (externalsorter) │ 373.78ms │
│ Queries Faster │ 0 │
│ Queries Slower │ 2 │
│ Queries with No Change │ 20 │
│ Queries with Failure │ 0 │
└───────────────────────────────┴───────────┘

Resource Usage

tpch10 — base (merge-base)

MetricValue
Wall time41.2s
Peak memory10.2 GiB
Avg memory7.8 GiB
CPU user434.7s
CPU sys26.4s
Peak spill0 B

tpch10 — branch

MetricValue
Wall time41.5s
Peak memory9.6 GiB
Avg memory7.5 GiB
CPU user436.0s
CPU sys27.4s
Peak spill0 B

File an issue against this benchmark runner

@Dandandan

Copy link
Copy Markdown
Contributor

run benchmark tpcds tpch_sort

@adriangbot

Copy link
Copy Markdown

🤖 Criterion benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4246870829-1257-bwm8p 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 externalsorter (32a6882) to e6b32fe (merge-base) diff
BENCH_NAME=tpch_sort
BENCH_COMMAND=cargo bench --features=parquet --bench tpch_sort
BENCH_FILTER=
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4246870829-1256-zqlsf 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 externalsorter (32a6882) to e6b32fe (merge-base) diff using: tpcds
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

Benchmark for this request failed.

Last 20 lines of output:

Click to expand
 struct_query_sql
substr
substr_index
substring
sum
to_char
to_hex
to_local_time
to_time
to_timestamp
topk_aggregate
topk_repartition
translate
trim
trunc
unhex
upper
uuid
window_query_sql
with_hashes

File an issue against this benchmark runner

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

run benchmark tpcds

env:
PREFER_HASH_JOIN: false

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4246955834-1261-fd4rq 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 externalsorter (32a6882) to e6b32fe (merge-base) diff using: tpcds
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

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
Details

Comparing HEAD and externalsorter
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ externalsorter ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1 │ 7.01 / 7.45 ±0.76 / 8.97 ms │ 6.86 / 7.33 ±0.76 / 8.86 ms │ no change │
│ QQuery 2 │ 143.89 / 145.42 ±1.02 / 146.77 ms │ 144.14 / 144.53 ±0.34 / 144.98 ms │ no change │
│ QQuery 3 │ 113.87 / 114.65 ±0.88 / 116.36 ms │ 112.84 / 113.44 ±0.33 / 113.81 ms │ no change │
│ QQuery 4 │ 1401.22 / 1414.73 ±10.96 / 1426.97 ms │ 1375.61 / 1415.42 ±34.40 / 1474.26 ms │ no change │
│ QQuery 5 │ 172.81 / 173.85 ±0.86 / 175.03 ms │ 171.04 / 173.32 ±1.69 / 176.20 ms │ no change │
│ QQuery 6 │ 849.72 / 867.23 ±21.92 / 910.12 ms │ 844.09 / 868.62 ±14.87 / 886.90 ms │ no change │
│ QQuery 7 │ 342.84 / 346.08 ±2.21 / 348.99 ms │ 340.64 / 346.49 ±3.18 / 349.42 ms │ no change │
│ QQuery 8 │ 114.66 / 118.26 ±2.55 / 121.27 ms │ 115.19 / 117.12 ±1.25 / 119.03 ms │ no change │
│ QQuery 9 │ 102.77 / 106.97 ±2.19 / 108.84 ms │ 101.33 / 104.25 ±2.34 / 107.23 ms │ no change │
│ QQuery 10 │ 106.87 / 108.20 ±1.11 / 109.99 ms │ 106.29 / 107.45 ±0.83 / 108.26 ms │ no change │
│ QQuery 11 │ 979.18 / 996.03 ±12.64 / 1016.91 ms │ 978.22 / 994.80 ±11.45 / 1005.19 ms │ no change │
│ QQuery 12 │ 45.78 / 46.90 ±0.77 / 47.81 ms │ 46.11 / 46.62 ±0.56 / 47.52 ms │ no change │
│ QQuery 13 │ 400.14 / 406.86 ±4.06 / 411.44 ms │ 399.86 / 401.85 ±1.71 / 404.03 ms │ no change │
│ QQuery 14 │ 1005.02 / 1010.73 ±4.14 / 1016.44 ms │ 1006.11 / 1017.87 ±5.97 / 1022.22 ms │ no change │
│ QQuery 15 │ 15.86 / 16.77 ±0.80 / 18.09 ms │ 17.18 / 17.56 ±0.44 / 18.16 ms │ no change │
│ QQuery 16 │ 7.52 / 8.15 ±0.80 / 9.71 ms │ 7.75 / 8.30 ±0.76 / 9.80 ms │ no change │
│ QQuery 17 │ 229.36 / 232.27 ±1.73 / 234.46 ms │ 228.99 / 231.71 ±1.82 / 233.57 ms │ no change │
│ QQuery 18 │ 128.73 / 130.55 ±1.18 / 132.14 ms │ 127.41 / 128.06 ±0.35 / 128.37 ms │ no change │
│ QQuery 19 │ 157.04 / 158.82 ±1.07 / 159.90 ms │ 154.25 / 156.86 ±1.97 / 159.56 ms │ no change │
│ QQuery 20 │ 14.36 / 15.46 ±1.21 / 17.78 ms │ 14.30 / 14.43 ±0.11 / 14.58 ms │ +1.07x faster │
│ QQuery 21 │ 20.67 / 21.23 ±0.67 / 22.52 ms │ 19.34 / 20.15 ±0.97 / 22.07 ms │ +1.05x faster │
│ QQuery 22 │ 497.76 / 508.34 ±13.13 / 533.70 ms │ 495.94 / 501.46 ±3.52 / 506.77 ms │ no change │
│ QQuery 23 │ 889.24 / 907.21 ±14.23 / 925.97 ms │ 893.40 / 899.61 ±4.57 / 906.89 ms │ no change │
│ QQuery 24 │ 387.44 / 388.95 ±1.42 / 390.89 ms │ 386.47 / 389.37 ±2.64 / 393.78 ms │ no change │
│ QQuery 25 │ 343.17 / 344.96 ±1.89 / 348.14 ms │ 342.38 / 345.21 ±2.02 / 348.12 ms │ no change │
│ QQuery 26 │ 81.18 / 82.14 ±0.92 / 83.78 ms │ 81.84 / 82.45 ±0.50 / 83.05 ms │ no change │
│ QQuery 27 │ 7.11 / 7.80 ±0.57 / 8.57 ms │ 6.95 / 7.12 ±0.20 / 7.52 ms │ +1.09x faster │
│ QQuery 28 │ 149.19 / 151.22 ±2.00 / 153.66 ms │ 148.65 / 149.84 ±1.42 / 152.26 ms │ no change │
│ QQuery 29 │ 284.41 / 285.07 ±0.66 / 286.29 ms │ 281.94 / 284.39 ±2.14 / 288.36 ms │ no change │
│ QQuery 30 │ 44.81 / 45.93 ±0.71 / 46.81 ms │ 43.96 / 46.06 ±2.08 / 49.33 ms │ no change │
│ QQuery 31 │ 171.15 / 172.97 ±1.43 / 174.91 ms │ 172.65 / 173.79 ±1.63 / 176.88 ms │ no change │
│ QQuery 32 │ 56.82 / 58.38 ±1.24 / 60.33 ms │ 56.43 / 57.76 ±1.03 / 58.88 ms │ no change │
│ QQuery 33 │ 142.10 / 144.90 ±2.15 / 147.95 ms │ 139.34 / 141.40 ±1.16 / 142.92 ms │ no change │
│ QQuery 34 │ 7.35 / 8.12 ±0.68 / 9.21 ms │ 7.06 / 7.24 ±0.21 / 7.64 ms │ +1.12x faster │
│ QQuery 35 │ 106.90 / 110.45 ±1.85 / 112.09 ms │ 109.46 / 110.15 ±0.43 / 110.71 ms │ no change │
│ QQuery 36 │ 6.83 / 7.03 ±0.13 / 7.24 ms │ 6.72 / 7.01 ±0.29 / 7.51 ms │ no change │
│ QQuery 37 │ 8.46 / 9.24 ±0.74 / 10.59 ms │ 8.33 / 8.96 ±0.50 / 9.80 ms │ no change │
│ QQuery 38 │ 84.81 / 87.66 ±3.86 / 95.24 ms │ 85.27 / 89.04 ±3.62 / 95.67 ms │ no change │
│ QQuery 39 │ 129.76 / 131.65 ±1.67 / 134.15 ms │ 124.77 / 129.08 ±2.58 / 132.06 ms │ no change │
│ QQuery 40 │ 109.28 / 117.12 ±8.65 / 130.76 ms │ 110.88 / 117.60 ±6.08 / 127.82 ms │ no change │
│ QQuery 41 │ 15.02 / 16.29 ±1.00 / 17.64 ms │ 15.41 / 17.04 ±1.11 / 18.27 ms │ no change │
│ QQuery 42 │ 107.23 / 108.91 ±1.34 / 110.82 ms │ 107.51 / 109.06 ±1.09 / 110.48 ms │ no change │
│ QQuery 43 │ 5.94 / 6.37 ±0.39 / 6.96 ms │ 6.18 / 6.25 ±0.08 / 6.40 ms │ no change │
│ QQuery 44 │ 11.99 / 12.97 ±0.82 / 14.26 ms │ 11.84 / 12.31 ±0.31 / 12.80 ms │ +1.05x faster │
│ QQuery 45 │ 50.23 / 51.40 ±0.97 / 53.18 ms │ 51.56 / 52.44 ±0.61 / 53.44 ms │ no change │
│ QQuery 46 │ 8.77 / 8.98 ±0.27 / 9.50 ms │ 8.65 / 9.04 ±0.27 / 9.34 ms │ no change │
│ QQuery 47 │ 736.62 / 740.19 ±2.82 / 744.07 ms │ 740.07 / 752.22 ±8.62 / 765.87 ms │ no change │
│ QQuery 48 │ 284.59 / 290.01 ±4.10 / 293.96 ms │ 293.83 / 297.49 ±2.75 / 300.53 ms │ no change │
│ QQuery 49 │ 253.71 / 255.10 ±2.14 / 259.35 ms │ 255.25 / 258.21 ±3.43 / 264.52 ms │ no change │
│ QQuery 50 │ 223.04 / 230.46 ±4.08 / 235.47 ms │ 226.51 / 231.44 ±4.77 / 240.07 ms │ no change │
│ QQuery 51 │ 176.96 / 182.13 ±3.82 / 187.71 ms │ 176.29 / 180.81 ±2.47 / 183.74 ms │ no change │
│ QQuery 52 │ 107.33 / 109.46 ±1.41 / 111.41 ms │ 107.57 / 108.99 ±1.05 / 110.55 ms │ no change │
│ QQuery 53 │ 102.43 / 103.30 ±0.65 / 104.40 ms │ 103.62 / 105.36 ±1.23 / 106.72 ms │ no change │
│ QQuery 54 │ 146.18 / 148.23 ±1.27 / 149.58 ms │ 148.37 / 149.35 ±0.63 / 150.05 ms │ no change │
│ QQuery 55 │ 107.79 / 108.25 ±0.41 / 108.94 ms │ 107.48 / 109.60 ±1.64 / 111.60 ms │ no change │
│ QQuery 56 │ 141.15 / 144.06 ±2.28 / 148.09 ms │ 143.45 / 143.90 ±0.33 / 144.31 ms │ no change │
│ QQuery 57 │ 172.66 / 176.77 ±2.31 / 179.17 ms │ 177.37 / 180.72 ±1.82 / 182.84 ms │ no change │
│ QQuery 58 │ 291.45 / 299.39 ±7.65 / 312.42 ms │ 292.57 / 302.23 ±6.72 / 310.96 ms │ no change │
│ QQuery 59 │ 196.29 / 199.92 ±2.07 / 201.76 ms │ 197.31 / 199.26 ±1.37 / 201.47 ms │ no change │
│ QQuery 60 │ 144.44 / 146.41 ±1.68 / 148.87 ms │ 143.09 / 144.42 ±1.24 / 146.47 ms │ no change │
│ QQuery 61 │ 13.83 / 13.98 ±0.10 / 14.11 ms │ 13.63 / 13.93 ±0.26 / 14.30 ms │ no change │
│ QQuery 62 │ 919.73 / 942.68 ±18.45 / 972.49 ms │ 932.03 / 955.86 ±13.20 / 971.95 ms │ no change │
│ QQuery 63 │ 104.37 / 106.07 ±1.62 / 108.70 ms │ 103.59 / 106.97 ±2.04 / 109.72 ms │ no change │
│ QQuery 64 │ 697.29 / 699.87 ±3.89 / 707.59 ms │ 691.38 / 695.19 ±4.92 / 704.88 ms │ no change │
│ QQuery 65 │ 257.00 / 261.25 ±3.46 / 264.97 ms │ 258.16 / 261.87 ±2.10 / 264.22 ms │ no change │
│ QQuery 66 │ 259.51 / 268.10 ±7.69 / 278.86 ms │ 250.70 / 262.91 ±7.62 / 271.65 ms │ no change │
│ QQuery 67 │ 319.33 / 321.91 ±1.79 / 324.36 ms │ 336.27 / 343.89 ±5.52 / 351.61 ms │ 1.07x slower │
│ QQuery 68 │ 9.10 / 9.97 ±0.98 / 11.30 ms │ 9.39 / 10.47 ±0.96 / 11.84 ms │ 1.05x slower │
│ QQuery 69 │ 104.04 / 104.66 ±0.34 / 105.00 ms │ 102.68 / 104.22 ±1.23 / 105.80 ms │ no change │
│ QQuery 70 │ 340.83 / 355.26 ±16.33 / 385.41 ms │ 351.12 / 353.81 ±4.33 / 362.46 ms │ no change │
│ QQuery 71 │ 133.55 / 137.03 ±1.90 / 139.00 ms │ 136.24 / 139.01 ±1.97 / 141.07 ms │ no change │
│ QQuery 72 │ 620.87 / 628.24 ±5.11 / 635.42 ms │ 609.20 / 627.19 ±9.93 / 635.88 ms │ no change │
│ QQuery 73 │ 7.29 / 8.88 ±1.62 / 11.43 ms │ 6.97 / 7.94 ±0.86 / 9.20 ms │ +1.12x faster │
│ QQuery 74 │ 627.03 / 629.77 ±3.36 / 635.82 ms │ 616.96 / 624.80 ±7.29 / 637.86 ms │ no change │
│ QQuery 75 │ 277.81 / 279.73 ±1.19 / 280.99 ms │ 279.22 / 281.63 ±2.30 / 285.95 ms │ no change │
│ QQuery 76 │ 133.72 / 135.05 ±1.27 / 137.09 ms │ 131.85 / 132.92 ±0.81 / 134.16 ms │ no change │
│ QQuery 77 │ 187.78 / 189.97 ±1.77 / 192.13 ms │ 187.66 / 189.23 ±1.01 / 190.37 ms │ no change │
│ QQuery 78 │ 346.27 / 349.32 ±3.11 / 354.42 ms │ 344.17 / 354.63 ±14.98 / 384.41 ms │ no change │
│ QQuery 79 │ 236.11 / 238.19 ±2.16 / 241.93 ms │ 237.78 / 240.48 ±1.71 / 242.15 ms │ no change │
│ QQuery 80 │ 324.53 / 328.03 ±1.94 / 330.48 ms │ 321.56 / 323.84 ±2.94 / 329.54 ms │ no change │
│ QQuery 81 │ 26.42 / 27.84 ±0.89 / 28.95 ms │ 26.32 / 27.51 ±1.28 / 29.55 ms │ no change │
│ QQuery 82 │ 197.20 / 199.01 ±1.20 / 200.43 ms │ 198.05 / 200.79 ±2.39 / 204.17 ms │ no change │
│ QQuery 83 │ 39.67 / 40.59 ±0.87 / 41.89 ms │ 39.70 / 40.73 ±0.99 / 42.43 ms │ no change │
│ QQuery 84 │ 48.91 / 50.07 ±0.91 / 51.07 ms │ 48.96 / 49.27 ±0.30 / 49.65 ms │ no change │
│ QQuery 85 │ 149.95 / 151.33 ±0.89 / 152.43 ms │ 148.70 / 151.71 ±2.59 / 156.46 ms │ no change │
│ QQuery 86 │ 38.87 / 39.91 ±0.74 / 41.18 ms │ 40.86 / 41.24 ±0.48 / 42.14 ms │ no change │
│ QQuery 87 │ 84.97 / 88.11 ±3.14 / 93.62 ms │ 88.48 / 93.26 ±2.59 / 96.23 ms │ 1.06x slower │
│ QQuery 88 │ 101.32 / 102.36 ±0.84 / 103.90 ms │ 102.27 / 107.65 ±8.60 / 124.69 ms │ 1.05x slower │
│ QQuery 89 │ 119.17 / 119.71 ±0.53 / 120.62 ms │ 120.50 / 122.28 ±0.91 / 122.95 ms │ no change │
│ QQuery 90 │ 23.99 / 24.45 ±0.52 / 25.25 ms │ 24.54 / 24.99 ±0.37 / 25.57 ms │ no change │
│ QQuery 91 │ 62.95 / 64.64 ±1.10 / 66.08 ms │ 64.97 / 65.48 ±0.76 / 66.98 ms │ no change │
│ QQuery 92 │ 58.76 / 59.16 ±0.38 / 59.77 ms │ 58.20 / 59.17 ±0.82 / 60.20 ms │ no change │
│ QQuery 93 │ 187.34 / 188.83 ±0.90 / 189.54 ms │ 191.90 / 193.75 ±0.97 / 194.61 ms │ no change │
│ QQuery 94 │ 62.13 / 62.99 ±0.73 / 64.29 ms │ 61.72 / 63.42 ±1.25 / 65.24 ms │ no change │
│ QQuery 95 │ 128.77 / 129.85 ±1.10 / 131.80 ms │ 128.83 / 130.56 ±0.88 / 131.22 ms │ no change │
│ QQuery 96 │ 72.12 / 74.37 ±1.31 / 75.93 ms │ 72.29 / 74.77 ±2.10 / 78.50 ms │ no change │
│ QQuery 97 │ 126.64 / 128.37 ±1.42 / 130.62 ms │ 128.40 / 130.65 ±1.52 / 133.03 ms │ no change │
│ QQuery 98 │ 153.54 / 157.50 ±2.41 / 160.45 ms │ 152.50 / 157.79 ±3.02 / 160.62 ms │ no change │
│ QQuery 99 │ 10778.07 / 10851.32 ±50.12 / 10897.00 ms │ 10813.12 / 10846.76 ±31.71 / 10892.84 ms │ no change │
└───────────┴──────────────────────────────────────────┴──────────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD) │ 31922.73ms │
│ Total Time (externalsorter) │ 31966.45ms │
│ Average Time (HEAD) │ 322.45ms │
│ Average Time (externalsorter) │ 322.89ms │
│ Queries Faster │ 6 │
│ Queries Slower │ 4 │
│ Queries with No Change │ 89 │
│ Queries with Failure │ 0 │
└───────────────────────────────┴────────────┘

Resource Usage

tpcds — base (merge-base)

MetricValue
Wall time160.0s
Peak memory5.8 GiB
Avg memory4.7 GiB
CPU user264.3s
CPU sys16.7s
Peak spill0 B

tpcds — branch

MetricValue
Wall time160.1s
Peak memory5.1 GiB
Avg memory4.4 GiB
CPU user264.4s
CPU sys17.4s
Peak spill0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance:c4a-highmem-16 (12 vCPU / 65 GiB)

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
Details

Comparing HEAD and externalsorter
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query ┃ HEAD ┃ externalsorter ┃ Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1 │ 49.74 / 50.95 ±0.80 / 52.26 ms │ 49.77 / 50.30 ±0.55 / 51.36 ms │ no change │
│ QQuery 2 │ 143.00 / 143.81 ±0.83 / 145.35 ms │ 138.66 / 139.17 ±0.36 / 139.58 ms │ no change │
│ QQuery 3 │ 162.98 / 163.26 ±0.21 / 163.53 ms │ 157.53 / 157.95 ±0.50 / 158.63 ms │ no change │
│ QQuery 4 │ 1612.56 / 1660.28 ±27.23 / 1688.23 ms │ 1600.19 / 1626.35 ±15.20 / 1645.67 ms │ no change │
│ QQuery 5 │ 269.80 / 279.75 ±5.67 / 286.05 ms │ 260.95 / 267.50 ±4.74 / 275.13 ms │ no change │
│ QQuery 6 │ 225.06 / 231.01 ±5.44 / 239.71 ms │ 213.47 / 216.62 ±3.33 / 220.82 ms │ +1.07x faster │
│ QQuery 7 │ 369.21 / 373.52 ±3.40 / 378.70 ms │ 362.94 / 364.15 ±1.10 / 365.71 ms │ no change │
│ QQuery 8 │ 176.29 / 180.13 ±2.51 / 183.75 ms │ 171.53 / 174.34 ±2.10 / 178.06 ms │ no change │
│ QQuery 9 │ 102.02 / 111.04 ±9.41 / 129.21 ms │ 100.99 / 103.19 ±2.14 / 106.76 ms │ +1.08x faster │
│ QQuery 10 │ 245.07 / 248.04 ±2.67 / 252.93 ms │ 233.82 / 238.41 ±2.95 / 242.19 ms │ no change │
│ QQuery 11 │ 808.76 / 824.14 ±10.53 / 836.10 ms │ 810.15 / 819.46 ±6.49 / 826.78 ms │ no change │
│ QQuery 12 │ 50.88 / 52.58 ±1.41 / 55.01 ms │ 50.86 / 51.56 ±0.71 / 52.81 ms │ no change │
│ QQuery 13 │ 399.54 / 401.90 ±2.09 / 405.30 ms │ 400.11 / 403.87 ±3.19 / 408.63 ms │ no change │
│ QQuery 14 │ 2028.96 / 2043.27 ±11.43 / 2062.97 ms │ 1902.55 / 1914.86 ±10.85 / 1932.72 ms │ +1.07x faster │
│ QQuery 15 │ 88.42 / 89.51 ±1.03 / 91.14 ms │ 87.27 / 87.73 ±0.45 / 88.54 ms │ no change │
│ QQuery 16 │ 153.89 / 155.19 ±1.80 / 158.68 ms │ 150.93 / 152.57 ±1.26 / 154.77 ms │ no change │
│ QQuery 17 │ 358.74 / 363.74 ±2.99 / 367.77 ms │ 349.17 / 353.82 ±2.78 / 357.20 ms │ no change │
│ QQuery 18 │ 281.14 / 281.63 ±0.43 / 282.22 ms │ 274.75 / 281.17 ±4.15 / 287.27 ms │ no change │
│ QQuery 19 │ 227.90 / 231.61 ±2.77 / 236.30 ms │ 221.61 / 224.17 ±2.06 / 226.49 ms │ no change │
│ QQuery 20 │ 88.12 / 89.47 ±1.22 / 91.77 ms │ 88.41 / 89.97 ±0.86 / 91.03 ms │ no change │
│ QQuery 21 │ 798.90 / 808.36 ±6.26 / 814.24 ms │ 668.78 / 673.38 ±3.70 / 677.90 ms │ +1.20x faster │
│ QQuery 22 │ 388.75 / 399.20 ±8.20 / 411.51 ms │ 354.85 / 356.72 ±2.03 / 360.51 ms │ +1.12x faster │
│ QQuery 23 │ 1088.60 / 1104.21 ±12.83 / 1120.18 ms │ 1007.69 / 1030.83 ±12.53 / 1043.52 ms │ +1.07x faster │
│ QQuery 24 │ 870.55 / 877.91 ±7.47 / 892.31 ms │ 856.79 / 867.18 ±6.16 / 872.77 ms │ no change │
│ QQuery 25 │ 417.13 / 423.92 ±5.61 / 432.55 ms │ 410.87 / 414.43 ±2.58 / 417.75 ms │ no change │
│ QQuery 26 │ 197.96 / 200.97 ±2.42 / 204.64 ms │ 196.74 / 198.52 ±1.63 / 201.33 ms │ no change │
│ QQuery 27 │ 367.12 / 371.91 ±4.35 / 378.67 ms │ 357.63 / 360.99 ±2.95 / 366.19 ms │ no change │
│ QQuery 28 │ 150.19 / 151.29 ±1.04 / 153.03 ms │ 150.96 / 161.33 ±12.39 / 185.19 ms │ 1.07x slower │
│ QQuery 29 │ 362.15 / 366.13 ±3.62 / 372.59 ms │ 353.01 / 356.10 ±2.05 / 358.46 ms │ no change │
│ QQuery 30 │ 53.48 / 55.39 ±1.12 / 56.79 ms │ 54.71 / 56.57 ±2.65 / 61.71 ms │ no change │
│ QQuery 31 │ 625.69 / 628.59 ±1.99 / 630.54 ms │ 608.30 / 611.04 ±1.82 / 612.67 ms │ no change │
│ QQuery 32 │ 146.06 / 147.59 ±1.33 / 149.77 ms │ 143.35 / 144.30 ±0.92 / 146.00 ms │ no change │
│ QQuery 33 │ 213.59 / 216.13 ±1.97 / 218.46 ms │ 205.35 / 208.49 ±2.17 / 211.51 ms │ no change │
│ QQuery 34 │ 179.36 / 181.67 ±1.21 / 182.70 ms │ 174.26 / 176.07 ±0.97 / 176.99 ms │ no change │
│ QQuery 35 │ 232.86 / 238.51 ±3.99 / 243.76 ms │ 225.71 / 226.83 ±0.76 / 227.90 ms │ no change │
│ QQuery 36 │ 272.93 / 274.49 ±1.27 / 276.02 ms │ 264.54 / 267.47 ±3.06 / 271.93 ms │ no change │
│ QQuery 37 │ 274.11 / 277.05 ±2.73 / 282.14 ms │ 260.50 / 264.81 ±2.52 / 267.87 ms │ no change │
│ QQuery 38 │ 191.40 / 194.86 ±2.31 / 198.45 ms │ 184.14 / 187.10 ±2.34 / 190.80 ms │ no change │
│ QQuery 39 │ 3617.17 / 3646.86 ±18.70 / 3667.45 ms │ 3294.92 / 3317.14 ±29.90 / 3376.26 ms │ +1.10x faster │
│ QQuery 40 │ 164.24 / 166.25 ±2.16 / 170.17 ms │ 159.06 / 162.57 ±3.56 / 168.98 ms │ no change │
│ QQuery 41 │ 15.41 / 16.22 ±1.43 / 19.07 ms │ 14.34 / 14.98 ±0.61 / 16.01 ms │ +1.08x faster │
│ QQuery 42 │ 164.30 / 164.65 ±0.40 / 165.42 ms │ 158.15 / 159.89 ±1.31 / 161.79 ms │ no change │
│ QQuery 43 │ 146.78 / 148.48 ±1.35 / 149.84 ms │ 137.90 / 138.84 ±1.51 / 141.84 ms │ +1.07x faster │
│ QQuery 44 │ 13.23 / 15.13 ±1.24 / 16.26 ms │ 12.62 / 13.15 ±0.57 / 14.15 ms │ +1.15x faster │
│ QQuery 45 │ 65.02 / 66.32 ±1.37 / 68.85 ms │ 66.32 / 67.17 ±0.76 / 68.54 ms │ no change │
│ QQuery 46 │ 343.05 / 345.47 ±2.48 / 350.17 ms │ 328.91 / 330.68 ±1.17 / 332.10 ms │ no change │
│ QQuery 47 │ 746.08 / 758.57 ±6.77 / 766.02 ms │ 712.07 / 717.79 ±4.98 / 726.32 ms │ +1.06x faster │
│ QQuery 48 │ 290.50 / 293.13 ±2.59 / 297.76 ms │ 285.39 / 290.38 ±4.62 / 299.00 ms │ no change │
│ QQuery 49 │ 258.58 / 261.84 ±2.10 / 264.11 ms │ 257.12 / 259.94 ±3.48 / 266.80 ms │ no change │
│ QQuery 50 │ 218.33 / 221.90 ±3.03 / 225.86 ms │ 217.04 / 218.17 ±1.09 / 219.97 ms │ no change │
│ QQuery 51 │ 228.10 / 229.72 ±1.64 / 232.87 ms │ 217.90 / 219.42 ±1.25 / 220.85 ms │ no change │
│ QQuery 52 │ 160.80 / 164.32 ±2.46 / 168.29 ms │ 157.52 / 159.53 ±1.82 / 162.55 ms │ no change │
│ QQuery 53 │ 166.15 / 168.23 ±1.17 / 169.62 ms │ 155.34 / 156.44 ±0.75 / 157.32 ms │ +1.08x faster │
│ QQuery 54 │ 250.91 / 257.78 ±4.15 / 263.02 ms │ 241.27 / 244.68 ±2.99 / 249.44 ms │ +1.05x faster │
│ QQuery 55 │ 161.96 / 164.74 ±2.30 / 167.83 ms │ 156.23 / 158.15 ±1.68 / 160.52 ms │ no change │
│ QQuery 56 │ 214.98 / 219.33 ±4.55 / 226.64 ms │ 207.29 / 208.81 ±1.32 / 210.52 ms │ no change │
│ QQuery 57 │ 356.96 / 358.95 ±1.69 / 360.93 ms │ 348.91 / 352.74 ±3.72 / 359.38 ms │ no change │
│ QQuery 58 │ 391.11 / 395.51 ±3.24 / 399.53 ms │ 373.90 / 377.29 ±2.57 / 380.86 ms │ no change │
│ QQuery 59 │ 289.96 / 292.41 ±2.07 / 295.73 ms │ 280.62 / 284.21 ±2.44 / 287.93 ms │ no change │
│ QQuery 60 │ 212.27 / 216.62 ±3.16 / 220.27 ms │ 205.52 / 207.67 ±1.41 / 209.58 ms │ no change │
│ QQuery 61 │ 282.98 / 288.94 ±4.52 / 295.97 ms │ 271.81 / 278.95 ±4.02 / 283.10 ms │ no change │
│ QQuery 62 │ 81.34 / 83.01 ±1.19 / 84.95 ms │ 75.65 / 76.16 ±0.44 / 76.89 ms │ +1.09x faster │
│ QQuery 63 │ 167.62 / 170.02 ±1.30 / 171.05 ms │ 156.78 / 158.38 ±1.02 / 159.67 ms │ +1.07x faster │
│ QQuery 64 │ 1447.80 / 1453.70 ±4.84 / 1459.36 ms │ 1416.77 / 1426.33 ±8.52 / 1439.37 ms │ no change │
│ QQuery 65 │ 332.63 / 335.47 ±1.84 / 338.39 ms │ 319.70 / 323.60 ±3.64 / 329.99 ms │ no change │
│ QQuery 66 │ 294.74 / 303.12 ±5.28 / 309.75 ms │ 241.97 / 245.41 ±2.61 / 248.39 ms │ +1.24x faster │
│ QQuery 67 │ 267.82 / 270.77 ±1.64 / 272.84 ms │ 274.05 / 277.32 ±3.64 / 284.19 ms │ no change │
│ QQuery 68 │ 395.80 / 403.19 ±6.40 / 414.43 ms │ 388.01 / 395.78 ±6.20 / 404.99 ms │ no change │
│ QQuery 69 │ 241.39 / 243.05 ±1.26 / 245.20 ms │ 229.77 / 232.45 ±1.80 / 234.21 ms │ no change │
│ QQuery 70 │ 438.48 / 440.98 ±2.52 / 444.54 ms │ 414.03 / 418.52 ±3.54 / 422.93 ms │ +1.05x faster │
│ QQuery 71 │ 204.47 / 207.46 ±2.60 / 211.64 ms │ 197.01 / 201.22 ±3.24 / 205.26 ms │ no change │
│ QQuery 72 │ 8234.94 / 8806.84 ±288.40 / 9000.55 ms │ 7393.54 / 7678.73 ±151.01 / 7816.87 ms │ +1.15x faster │
│ QQuery 73 │ 177.60 / 181.67 ±2.63 / 184.59 ms │ 171.45 / 175.37 ±4.00 / 183.02 ms │ no change │
│ QQuery 74 │ 568.83 / 577.38 ±5.58 / 583.13 ms │ 541.29 / 549.82 ±4.41 / 553.64 ms │ no change │
│ QQuery 75 │ 504.31 / 516.57 ±6.96 / 525.41 ms │ 488.70 / 494.04 ±5.93 / 505.26 ms │ no change │
│ QQuery 76 │ 134.29 / 138.36 ±2.20 / 140.68 ms │ 135.17 / 137.80 ±1.74 / 140.62 ms │ no change │
│ QQuery 77 │ 273.85 / 279.12 ±2.82 / 281.87 ms │ 261.98 / 268.83 ±5.72 / 275.75 ms │ no change │
│ QQuery 78 │ 559.82 / 565.84 ±4.92 / 572.65 ms │ 543.23 / 546.52 ±2.70 / 549.62 ms │ no change │
│ QQuery 79 │ 332.91 / 338.18 ±3.76 / 344.34 ms │ 323.71 / 328.48 ±2.85 / 332.24 ms │ no change │
│ QQuery 80 │ 451.16 / 461.80 ±8.86 / 471.83 ms │ 440.33 / 451.68 ±6.86 / 458.92 ms │ no change │
│ QQuery 81 │ 58.09 / 62.79 ±4.42 / 70.88 ms │ 56.14 / 60.33 ±4.38 / 67.49 ms │ no change │
│ QQuery 82 │ 315.86 / 318.35 ±3.05 / 324.20 ms │ 293.30 / 295.47 ±1.69 / 297.35 ms │ +1.08x faster │
│ QQuery 83 │ 66.32 / 67.42 ±1.29 / 69.78 ms │ 63.49 / 65.19 ±1.51 / 67.97 ms │ no change │
│ QQuery 84 │ 65.81 / 66.72 ±0.66 / 67.50 ms │ 62.26 / 63.12 ±0.90 / 64.81 ms │ +1.06x faster │
│ QQuery 85 │ 176.59 / 179.81 ±2.14 / 182.52 ms │ 166.38 / 168.19 ±2.26 / 172.64 ms │ +1.07x faster │
│ QQuery 86 │ 45.63 / 46.60 ±0.89 / 48.20 ms │ 44.58 / 45.77 ±0.92 / 46.88 ms │ no change │
│ QQuery 87 │ 192.74 / 194.62 ±1.92 / 198.25 ms │ 185.30 / 187.57 ±2.30 / 191.42 ms │ no change │
│ QQuery 88 │ 297.82 / 310.03 ±6.59 / 317.38 ms │ 275.13 / 285.26 ±5.81 / 291.71 ms │ +1.09x faster │
│ QQuery 89 │ 170.62 / 174.64 ±4.64 / 183.71 ms │ 159.64 / 163.07 ±4.05 / 170.83 ms │ +1.07x faster │
│ QQuery 90 │ 40.99 / 41.66 ±0.50 / 42.40 ms │ 37.74 / 38.55 ±0.57 / 39.24 ms │ +1.08x faster │
│ QQuery 91 │ 70.57 / 71.76 ±0.91 / 73.38 ms │ 68.61 / 69.82 ±1.00 / 71.02 ms │ no change │
│ QQuery 92 │ 82.07 / 83.19 ±0.76 / 84.21 ms │ 80.72 / 81.13 ±0.39 / 81.84 ms │ no change │
│ QQuery 93 │ 380.35 / 389.69 ±6.39 / 397.77 ms │ 403.81 / 411.73 ±5.60 / 420.16 ms │ 1.06x slower │
│ QQuery 94 │ 92.28 / 93.41 ±0.71 / 94.34 ms │ 89.67 / 92.82 ±4.10 / 100.87 ms │ no change │
│ QQuery 95 │ 166.06 / 167.38 ±1.03 / 168.77 ms │ 162.40 / 164.19 ±1.14 / 165.74 ms │ no change │
│ QQuery 96 │ 126.90 / 128.13 ±0.87 / 129.44 ms │ 120.92 / 122.47 ±1.78 / 125.84 ms │ no change │
│ QQuery 97 │ 198.32 / 200.22 ±1.17 / 201.88 ms │ 192.65 / 194.61 ±1.81 / 197.68 ms │ no change │
│ QQuery 98 │ 183.37 / 185.92 ±1.98 / 187.89 ms │ 181.32 / 183.52 ±1.17 / 184.45 ms │ no change │
│ QQuery 99 │ 205.39 / 207.60 ±2.10 / 211.09 ms │ 191.93 / 195.48 ±2.21 / 197.73 ms │ +1.06x faster │
└───────────┴────────────────────────────────────────┴────────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary ┃ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD) │ 42520.79ms │
│ Total Time (externalsorter) │ 39892.64ms │
│ Average Time (HEAD) │ 429.50ms │
│ Average Time (externalsorter) │ 402.96ms │
│ Queries Faster │ 25 │
│ Queries Slower │ 2 │
│ Queries with No Change │ 72 │
│ Queries with Failure │ 0 │
└───────────────────────────────┴────────────┘

Resource Usage

tpcds — base (merge-base)

MetricValue
Wall time213.1s
Peak memory28.6 GiB
Avg memory6.9 GiB
CPU user874.8s
CPU sys90.3s
Peak spill0 B

tpcds — branch

MetricValue
Wall time199.8s
Peak memory18.4 GiB
Avg memory6.0 GiB
CPU user842.4s
CPU sys71.8s
Peak spill0 B

File an issue against this benchmark runner

github-merge-queueBot pushed a commit that referenced this pull request Apr 15, 2026
## Which issue does this PR close?
- Partially addresses #21543. Also needed to properly evaluate the
ExternalSorter refactor in #21629, which improves the merge path.
## Rationale for this change
Current sort benchmarks use 100K rows across 8 partitions (~12.5K rows
per partition, ~100KB for integers). This falls below the
`sort_in_place_threshold_bytes` (1MB), so the "sort partitioned"
benchmarks always take the concat-and-sort-in-place path and never
exercise the sort-then-merge path that dominates real workloads.
## What changes are included in this PR?
Parameterizes the sort benchmark on input size, running each case at
both 100K rows (existing) and 1M rows (new). At 1M rows, each partition
holds ~125K rows (~1MB for integers), which exercises the merge path.
- `INPUT_SIZE` constant replaced with `INPUT_SIZES` array: `[(100_000,
"100k"), (1_000_000, "1M")]`
- `DataGenerator` takes `input_size` as a constructor parameter
- All stream generator functions accept `input_size`
- Benchmark names include size label (e.g. `sort partitioned i64 100k`,
`sort partitioned i64 10M`)
- Data distribution and cardinality ratios are preserved across sizes
## Are these changes tested?
Benchmark compiles and runs. No functional test changes.
## Are there any user-facing changes?
No.
@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

run benchmark sort

@adriangbot

Copy link
Copy Markdown

🤖 Criterion benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4253348811-1301-2rfg4 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 externalsorter (689dfd2) to d0692b8 (merge-base) diff
BENCH_NAME=sort
BENCH_COMMAND=cargo bench --features=parquet --bench sort
BENCH_FILTER=
Results will be posted here when complete


File an issue against this benchmark runner

/// `─────────────────' │
/// spills
/// ┌──────────┐ ┌────────────┐ ┌──────┐ ┌────────────┐
/// │ Incoming │────▶│ Batch │────▶│ Sort │────▶│ Sorted Run │

@DandandanDandandanApr 15, 2026

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.

In the current approach, it would be worth it to "push down" the target batch size to the inner operation, so the output of the previous stage already is of the higher batch size instead of doing another copy.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

@andygrove and I have been discussing this in the context of Comet, where for some Spark stages that get translated to native plans we'd possibly want to set different target batch sizes. What you're proposing sounds even more granular, where individual operators could potentially advertise an ideal input batch size, though this could get complicated fast based on schema. Maybe some sort of trait on operators to advertise when they want larger batch sizes, and the optimizer could figure out what that target should be?

Regardless, a general solution seems out of scope for this PR.

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.

Yeah I think something like that could work.

The propagation doesn't seem too complex I think, just change the target batch size of te inner op based on the desired one.

I agree it is out of scope.

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

I fear my sort benchmark scale up might have killed the benchmark bot :(

}
}
for batch in &completed {
self.sort_and_store_run(batch)?;

@DandandanDandandanApr 15, 2026

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.

Nice - I wonder if a part of the speedup comes from this, sorting batch immediately (while in CPU cache) instead of waiting to the end.

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

run benchmark sort

@adriangbot

Copy link
Copy Markdown

🤖 Criterion benchmark running (GKE) | trigger
Instance:c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c4255649635-1332-2jl79 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 externalsorter (0198302) to 5c653be (merge-base) diff
BENCH_NAME=sort
BENCH_COMMAND=cargo bench --features=parquet --bench sort
BENCH_FILTER=
Results will be posted here when complete


File an issue against this benchmark runner

github-merge-queueBot pushed a commit that referenced this pull request Apr 15, 2026
…21657)
## Which issue does this PR close?
- Closes #.
## Rationale for this change
PR #21620 (commit 5c653be) ported
`test_aggregate_dynamic_filter_parquet_e2e` from Rust to sqllogictest
using `analyze_categories = 'rows'`, which includes exact pushdown
metrics. These metrics are nondeterministic under parallel execution —
the order in which Partial aggregates publish dynamic filter updates
races against when the scan reads each partition — so the expected
output is flaky.
Noticed on #21629 ([CI
run](https://github.com/apache/datafusion/actions/runs/24472961090/job/71518239089?pr=21629))
and confirmed on main ([CI
run](https://github.com/apache/datafusion/actions/runs/24467213913/job/71497866154)).
## What changes are included in this PR?
Switch the `agg_dyn_e2e` test to `analyze_level = summary` +
`analyze_categories = 'none'`, suppressing nondeterministic metrics.
This matches the approach already used by the other aggregate dynamic
filter tests in the same file. The original Rust test only asserted
`matched < 4` (i.e. some pruning happened); the important invariant —
that the `DynamicFilter [ column1@0 > 4 ]` text and pruning predicate
are correct — is still verified.
## Are these changes tested?
Yes — the test itself is what is being fixed.
## Are there any user-facing changes?
No.
@Dandandan

Copy link
Copy Markdown
Contributor

Would be nice to see results in sort bench / sort_tpch etc. to see if we didnt have any regressions.

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

Would be nice to see results in sort bench / sort_tpch etc. to see if we didnt have any regressions.

I’ll try to run locally with the scaled up sort benchmark. We may want to consider scaling some of the scenarios independently if 1M is too big to apply across the board for the bot.

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

Benchmark Analysis: externalsorter vs main

Ran cargo bench --bench sort -p datafusion on both branches.

Improvements (numeric, StringView, single-column string)

BenchmarkexternalsortermainSpeedup
sort i64 100k2.40 ms3.88 ms1.61x
sort f64 100k2.61 ms3.94 ms1.51x
sort merge i64 1M26.6 ms38.5 ms1.45x
sort i64 1M33.8 ms45.5 ms1.35x
sort f64 1M35.8 ms46.4 ms1.30x
sort utf8 high cardinality 1M59.7 ms74.0 ms1.24x
sort utf8 view tuple 1M8.1 ms9.1 ms1.13x

Regressions (multi-column StringArray and Dictionary)

BenchmarkexternalsortermainSlowdown
sort utf8 tuple 100k (3x StringArray)23.7 ms9.5 ms2.5x
sort utf8 tuple 1M (3x StringArray)272 ms111 ms2.5x
sort mixed dictionary tuple 1M (3x dict + i64)283 ms108 ms2.6x
sort utf8 dictionary tuple 1M (3x dict)92.4 ms78.5 ms1.18x

Root cause

The coalesce-then-sort pipeline does: coalesce (copy all column data) -> lexsort_to_indices -> take (random-access scatter-gather) -> chunk back to batch_size. With multiple StringArray or Dictionary columns at 32K rows, the take scatter-gathers across ~1.9 MB of string heap data, exceeding L2 cache.

Schemas that don't regress help pinpoint the cause:

  • Single StringArray (e.g. sort utf8 high cardinality 1M, +1.24x): one ~640KB string buffer fits in L2 during take
  • StringViewArray (e.g. sort utf8 view tuple 1M, +1.13x): take copies fixed-size 16-byte view structs — no heap random access
  • Fixed-width (i64, f64): coalesce is memcpy, take is sequential — all cache-friendly

Benchmark batch size

The sort benchmark uses BATCH_SIZE = 1024, while DataFusion's default is 8192. This makes the coalesce expand 32x (1024 -> 32768) instead of 4x (8192 -> 32768), amplifying the copy cost. Small batches are a valid scenario though — filters, joins, and sources with pushdown can all produce sub-8192 batches.

Proposed fix

Arrow's BatchCoalescer has a with_biggest_coalesce_batch_size(Some(limit)) option: batches larger than limit bypass coalescing and pass through directly. For schemas with non-view variable-length columns (StringArray, BinaryArray, DictionaryArray), set this to batch_size. This way:

  • Full-size batches (>= 8192 rows) pass through without string copying — sorted directly as individual runs
  • Small batches still coalesce to reduce fan-in
  • Fixed-width and StringView schemas keep the full 32K coalesce target unchanged

@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

Marking as draft while we explore performance trade-offs. I don't want to accidentally merge this yet.

@mbutrovich
mbutrovich marked this pull request as draft April 16, 2026 15:14
@mbutrovich

Copy link
Copy Markdown
ContributorAuthor

More brainstorming with Claude:

Proposed fix

Don't coalesce schemas that have variable-length non-view columns (StringArray, BinaryArray, LargeStringArray, LargeBinaryArray, DictionaryArray with string/binary values). For these schemas, set the coalesce target to batch_size instead of sort_coalesce_target_rows:

  • Full-size batches pass through uncoalesced and sort individually, same as main — no regression
  • Small batches (from filters, joins, pushdown) coalesce up to batch_size only — some fan-in reduction without blowing cache
  • StringView and fixed-width schemas keep the full 32K coalesce target and retain all speedups

Fan-in reduction is the price we pay for StringArray schemas. We can't optimize the merge if the sort itself is 2.5x slower getting there.

Comet does not support StringView — all string columns use StringArray, so this regression directly affects Comet workloads.

Why check all columns, not just sort keys?

take reorders all columns in the batch, not just sort keys. Wide schemas (e.g. small string key + 70KB string value) are especially vulnerable — coalescing to 32K means take scatter-gathers across ~2.2GB of value data.

Alternatives considered

Smaller intermediate target (e.g. 16K): Any coalescing beyond batch_size amplifies cache pressure for wide schemas proportionally. No clear sweet spot.

Convert StringArray → StringView before take: The gather (conversion) is cheap and take on views is cheap, but the resulting views point to the original unsorted buffer. No memory freed until the entire buffer drops — ~2x memory bloat, wrong tradeoff for a spilling sort.

@gratus00gratus00 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Learning review

Comment on lines +656 to +659
// - This works because sort() only enters this path when
// merge_reservation > 0, guaranteeing pool headroom for cursors.
// When merge_reservation == 0, sort() takes the spill path instead.
let streams = all_runs

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

if i'm not mistaken merge_sorted_runs() is also being called on the non-spill path inside sort() when self.spilled_before() evaluates to false, where merge_reservation is never pre-reserved.

maybe we can make the comment more descriptive on the different headroom reliance of the different paths?

Comment on lines -352 to -358
// Transfer the pre-reserved merge memory to the streaming merge
// using `take()` instead of `new_empty()`. This ensures the merge
// stream starts with `sort_spill_reservation_bytes` already
// allocated, preventing starvation when concurrent sort partitions
// compete for pool memory. `take()` moves the bytes atomically
// without releasing them back to the pool, so other partitions
// cannot race to consume the freed memory.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This comment is quite useful, maybe we should keep it, could help future developers know why take is being used!

new_columns.push(Arc::clone(array));
}
}
if self.merge_reservation.size() > 0 && self.sorted_runs.len() > 1 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hi, i'm tracing the spill cycles, and the first spill's merge_reservation value starts at 0 while others grow at the end of spill_sorted_runs

the second spill could be something small like 1024 and still take the merge path

is >0 just a good enough heuristic we are using without trying to guarantee actual headroom for the merge process?

feel free to correct me, i'm new and i'm trying to learn!!

Rich-T-kid pushed a commit to Rich-T-kid/datafusion that referenced this pull request Apr 21, 2026
…e#21630)
## Which issue does this PR close?
- Partially addresses apache#21543. Also needed to properly evaluate the
ExternalSorter refactor in apache#21629, which improves the merge path.
## Rationale for this change
Current sort benchmarks use 100K rows across 8 partitions (~12.5K rows
per partition, ~100KB for integers). This falls below the
`sort_in_place_threshold_bytes` (1MB), so the "sort partitioned"
benchmarks always take the concat-and-sort-in-place path and never
exercise the sort-then-merge path that dominates real workloads.
## What changes are included in this PR?
Parameterizes the sort benchmark on input size, running each case at
both 100K rows (existing) and 1M rows (new). At 1M rows, each partition
holds ~125K rows (~1MB for integers), which exercises the merge path.
- `INPUT_SIZE` constant replaced with `INPUT_SIZES` array: `[(100_000,
"100k"), (1_000_000, "1M")]`
- `DataGenerator` takes `input_size` as a constructor parameter
- All stream generator functions accept `input_size`
- Benchmark names include size label (e.g. `sort partitioned i64 100k`,
`sort partitioned i64 10M`)
- Data distribution and cardinality ratios are preserved across sizes
## Are these changes tested?
Benchmark compiles and runs. No functional test changes.
## Are there any user-facing changes?
No.
Rich-T-kid pushed a commit to Rich-T-kid/datafusion that referenced this pull request Apr 21, 2026
…pache#21657)
## Which issue does this PR close?
- Closes #.
## Rationale for this change
PR apache#21620 (commit 5c653be) ported
`test_aggregate_dynamic_filter_parquet_e2e` from Rust to sqllogictest
using `analyze_categories = 'rows'`, which includes exact pushdown
metrics. These metrics are nondeterministic under parallel execution —
the order in which Partial aggregates publish dynamic filter updates
races against when the scan reads each partition — so the expected
output is flaky.
Noticed on apache#21629 ([CI
run](https://github.com/apache/datafusion/actions/runs/24472961090/job/71518239089?pr=21629))
and confirmed on main ([CI
run](https://github.com/apache/datafusion/actions/runs/24467213913/job/71497866154)).
## What changes are included in this PR?
Switch the `agg_dyn_e2e` test to `analyze_level = summary` +
`analyze_categories = 'none'`, suppressing nondeterministic metrics.
This matches the approach already used by the other aggregate dynamic
filter tests in the same file. The original Rust test only asserted
`matched < 4` (i.e. some pruning happened); the important invariant —
that the `DynamicFilter [ column1@0 > 4 ]` text and pruning predicate
are correct — is still verified.
## Are these changes tested?
Yes — the test itself is what is being fixed.
## Are there any user-facing changes?
No.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commonRelated to common cratecoreCore DataFusion cratedocumentationImprovements or additions to documentationexecutionRelated to the execution crateperformanceMake DataFusion fasterphysical-planChanges to the physical-plan cratesqllogictestSQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@mbutrovich@adriangbot@Dandandan@gratus00