Skip to content

bench(functions-aggregate): benchmark coalescing peer first_value into a struct (#23682) - #24559

Open
zhuqi-lucas wants to merge 2 commits into
apache:mainfrom
zhuqi-lucas:bench/first-last-coalesce-peers
Open

bench(functions-aggregate): benchmark coalescing peer first_value into a struct (#23682)#24559
zhuqi-lucas wants to merge 2 commits into
apache:mainfrom
zhuqi-lucas:bench/first-last-coalesce-peers

Conversation

@zhuqi-lucas

@zhuqi-lucas zhuqi-lucas commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

The CoalesceFirstLast optimizer rule (#23682) rewrites N peer first_value(col ORDER BY o) expressions that share one ORDER BY into a single first_value(named_struct(...) ORDER BY o). The win is at the accumulator level: N independent argmax passes collapse into one struct-valued argmax — one per-row ordering compare instead of N, one slot per group instead of N.

This PR adds the benchmark that quantifies that win, so #23682 can cite concrete numbers as its performance justification. Nothing in the suite measured this head-to-head before.

What changes are included in this PR?

Adds coalesce_comparison_bench to functions-aggregate/benches/first_last.rs, producing two cases in the same run:

  • first_value coalesce_peers(i64,utf8,f64) separate x3 — three independent primitive first_value GroupsAccumulators (the pre-rewrite plan)
  • first_value coalesce_peers(i64,utf8,f64) coalesced struct — one struct-valued GroupsAccumulator carrying the same three columns (the post-rewrite plan)

The struct path exercises the native nested GroupsAccumulator merged in #23628. Reuses the existing prepare_typed_groups_accumulator / create_struct_array helpers; no new dependencies or imports.

Are these changes tested?

Benchmark-only; compiles under cargo check --benches. Triggered run benchmark first_last on this PR for the head-to-head numbers — posted in a comment below.

Copilot AI lite review requested due to automatic review settings August 21, 2026 10:05
@github-actions github-actions Bot added the functions Changes to functions implementation label Aug 21, 2026

Copilot AI left a comment

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.

Pull request overview

Adds a benchmark comparing separate primitive first_value accumulators with a coalesced struct accumulator.

Changes:

  • Adds coalesce-peers benchmark cases.
  • Covers i64, utf8, and f64 inputs.
  • Registers the benchmark in the aggregate suite.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codecov-commenter

codecov-commenter commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.34%. Comparing base (5f0ba13) to head (7b438cb).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24559      +/-   ##
==========================================
- Coverage   81.34%   81.34%   -0.01%     
==========================================
  Files        1117     1117              
  Lines      397528   397528              
  Branches   397528   397528              
==========================================
- Hits       323385   323372      -13     
- Misses      55225    55236      +11     
- Partials    18918    18920       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@zhuqi-lucas

Copy link
Copy Markdown
Contributor Author

run benchmark first_last

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5369986874-1838-g6qzf 6.12.85+ #1 SMP Sat Jun 27 09:31:30 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 bench/first-last-coalesce-peers (58c0117) to 5610e58 (merge-base) diff

Run configuration
run benchmark first_last

Results will be posted here when complete


File an issue against this benchmark runner

@zhuqi-lucas zhuqi-lucas changed the title bench(functions-aggregate): add coalesce-peers first_value comparison bench(functions-aggregate): benchmark coalescing peer first_value into a struct (#23682) Aug 21, 2026
@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

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

Comparing bench/first-last-coalesce-peers (58c0117) to 5610e58 (merge-base) diff

Run configuration
run benchmark first_last
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

group                                                                  HEAD                                   bench_first-last-coalesce-peers
-----                                                                  ----                                   -------------------------------
first_value coalesce_peers(i64,utf8,f64) coalesced struct                                                     1.00     35.1±0.08ms        ? ?/sec
first_value coalesce_peers(i64,utf8,f64) separate x3                                                          1.00     90.3±0.22ms        ? ?/sec
first_value evaluate_bench list<i64>[4] nulls=0%, all                  1.00    458.0±6.59µs        ? ?/sec    1.01   462.6±12.51µs        ? ?/sec
first_value evaluate_bench list<i64>[4] nulls=90%, all                 1.00    549.6±4.29µs        ? ?/sec    1.02    561.2±4.63µs        ? ?/sec
first_value evaluate_bench list<struct(i64,utf8)>[4] nulls=0%, all     1.00   1024.5±7.48µs        ? ?/sec    1.00   1020.9±4.97µs        ? ?/sec
first_value evaluate_bench list<struct(i64,utf8)>[4] nulls=90%, all    1.26   1219.5±6.03µs        ? ?/sec    1.00   965.2±31.00µs        ? ?/sec
first_value evaluate_bench map<utf8,i64> nulls=0%, all                 1.00    871.2±5.44µs        ? ?/sec    1.00    868.4±7.41µs        ? ?/sec
first_value evaluate_bench map<utf8,i64> nulls=90%, all                1.03   1089.2±4.51µs        ? ?/sec    1.00   1058.2±5.62µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=false, all                 1.00     17.1±1.63µs        ? ?/sec    1.00     17.1±1.52µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=false, first(2)            1.00     12.9±1.14µs        ? ?/sec    1.02     13.1±1.65µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=true, all                  1.05     17.1±2.12µs        ? ?/sec    1.00     16.3±1.11µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=true, first(2)             1.06     18.4±2.48µs        ? ?/sec    1.00     17.3±0.73µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=false, all                1.00     16.9±1.64µs        ? ?/sec    1.01     17.1±1.68µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=false, first(2)           1.01     18.0±2.05µs        ? ?/sec    1.00     17.7±1.26µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=true, all                 1.01     16.8±2.12µs        ? ?/sec    1.00     16.7±2.05µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=true, first(2)            1.00     18.2±2.32µs        ? ?/sec    1.00     18.2±2.33µs        ? ?/sec
first_value evaluate_bench struct(i64,utf8,f64) nulls=0%, all          1.00   703.1±14.04µs        ? ?/sec    1.02   714.7±13.99µs        ? ?/sec
first_value evaluate_bench struct(i64,utf8,f64) nulls=90%, all         1.33  1046.8±15.12µs        ? ?/sec    1.00   785.1±13.33µs        ? ?/sec
first_value merge_bench list<i64>[4] nulls=0%                          1.00     37.0±0.09ms        ? ?/sec    1.01     37.3±0.12ms        ? ?/sec
first_value merge_bench list<i64>[4] nulls=90%                         1.00     37.3±0.11ms        ? ?/sec    1.01     37.6±0.14ms        ? ?/sec
first_value merge_bench list<struct(i64,utf8)>[4] nulls=0%             1.00     39.6±0.10ms        ? ?/sec    1.00     39.5±0.17ms        ? ?/sec
first_value merge_bench list<struct(i64,utf8)>[4] nulls=90%            1.00     40.8±0.21ms        ? ?/sec    1.00     40.6±0.10ms        ? ?/sec
first_value merge_bench map<utf8,i64> nulls=0%                         1.00     39.2±0.15ms        ? ?/sec    1.00     39.4±0.15ms        ? ?/sec
first_value merge_bench map<utf8,i64> nulls=90%                        1.00     40.9±0.16ms        ? ?/sec    1.00     40.9±0.18ms        ? ?/sec
first_value merge_bench nulls=0%, filter=false                         1.00     34.9±0.09ms        ? ?/sec    1.00     34.9±0.06ms        ? ?/sec
first_value merge_bench nulls=0%, filter=true                          1.00     35.0±0.11ms        ? ?/sec    1.00     34.9±0.08ms        ? ?/sec
first_value merge_bench nulls=90%, filter=false                        1.01     37.8±0.15ms        ? ?/sec    1.00     37.5±0.04ms        ? ?/sec
first_value merge_bench nulls=90%, filter=true                         1.01     37.9±0.21ms        ? ?/sec    1.00     37.5±0.09ms        ? ?/sec
first_value merge_bench struct(i64,utf8,f64) nulls=0%                  1.00     39.5±0.12ms        ? ?/sec    1.00     39.4±0.09ms        ? ?/sec
first_value merge_bench struct(i64,utf8,f64) nulls=90%                 1.00     41.6±0.13ms        ? ?/sec    1.01     41.8±0.09ms        ? ?/sec
first_value trivial_update_bench nulls=0%, ignore_nulls=false          1.00      2.6±0.07µs        ? ?/sec    1.00      2.6±0.07µs        ? ?/sec
first_value trivial_update_bench nulls=0%, ignore_nulls=true           1.00      2.6±0.07µs        ? ?/sec    1.01      2.6±0.16µs        ? ?/sec
first_value trivial_update_bench nulls=90%, ignore_nulls=false         1.00      2.9±0.10µs        ? ?/sec    1.00      2.8±0.10µs        ? ?/sec
first_value trivial_update_bench nulls=90%, ignore_nulls=true          1.01      3.6±0.03µs        ? ?/sec    1.00      3.6±0.02µs        ? ?/sec
first_value update_bench list<i64>[4] nulls=0%                         1.00     31.9±0.09ms        ? ?/sec    1.03     32.8±0.12ms        ? ?/sec
first_value update_bench list<i64>[4] nulls=90%                        1.00     32.3±0.15ms        ? ?/sec    1.03     33.1±0.10ms        ? ?/sec
first_value update_bench list<struct(i64,utf8)>[4] nulls=0%            1.00     34.3±0.17ms        ? ?/sec    1.02     35.1±0.16ms        ? ?/sec
first_value update_bench list<struct(i64,utf8)>[4] nulls=90%           1.00     35.7±0.15ms        ? ?/sec    1.01     36.2±0.08ms        ? ?/sec
first_value update_bench map<utf8,i64> nulls=0%                        1.00     34.2±0.15ms        ? ?/sec    1.02     35.0±0.14ms        ? ?/sec
first_value update_bench map<utf8,i64> nulls=90%                       1.00     36.0±0.14ms        ? ?/sec    1.02     36.6±0.18ms        ? ?/sec
first_value update_bench nulls=0%, filter=false                        1.01     30.2±0.06ms        ? ?/sec    1.00     30.0±0.06ms        ? ?/sec
first_value update_bench nulls=0%, filter=true                         1.01     46.3±0.19ms        ? ?/sec    1.00     46.0±0.23ms        ? ?/sec
first_value update_bench nulls=90%, filter=false                       1.01     33.8±0.07ms        ? ?/sec    1.00     33.4±0.04ms        ? ?/sec
first_value update_bench nulls=90%, filter=true                        1.04     47.0±0.41ms        ? ?/sec    1.00     45.4±0.39ms        ? ?/sec
first_value update_bench struct(i64,utf8,f64) nulls=0%                 1.00     34.6±0.09ms        ? ?/sec    1.01     35.0±0.07ms        ? ?/sec
first_value update_bench struct(i64,utf8,f64) nulls=90%                1.00     36.7±0.08ms        ? ?/sec    1.02     37.5±0.08ms        ? ?/sec
last_value evaluate_bench nulls=0%, filter=false, all                  1.00     16.8±1.54µs        ? ?/sec    1.04     17.5±2.03µs        ? ?/sec
last_value evaluate_bench nulls=0%, filter=false, first(2)             1.03     18.4±2.08µs        ? ?/sec    1.00     17.8±1.09µs        ? ?/sec
last_value evaluate_bench nulls=0%, filter=true, all                   1.01     17.2±1.98µs        ? ?/sec    1.00     17.0±1.85µs        ? ?/sec
last_value evaluate_bench nulls=0%, filter=true, first(2)              1.00     17.8±1.35µs        ? ?/sec    1.03     18.3±2.11µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=false, all                 1.00     17.0±1.71µs        ? ?/sec    1.00     17.0±1.58µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=false, first(2)            1.00     18.4±1.98µs        ? ?/sec    1.02     18.8±2.15µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=true, all                  1.00     16.4±1.11µs        ? ?/sec    1.03     16.8±1.73µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=true, first(2)             1.00     17.6±1.58µs        ? ?/sec    1.01     17.8±1.41µs        ? ?/sec
last_value merge_bench list<i64>[4] nulls=0%                           1.00     37.4±0.11ms        ? ?/sec    1.00     37.4±0.12ms        ? ?/sec
last_value merge_bench list<i64>[4] nulls=90%                          1.00     37.9±0.13ms        ? ?/sec    1.00     37.7±0.12ms        ? ?/sec
last_value merge_bench list<struct(i64,utf8)>[4] nulls=0%              1.01     39.8±0.13ms        ? ?/sec    1.00     39.6±0.12ms        ? ?/sec
last_value merge_bench list<struct(i64,utf8)>[4] nulls=90%             1.01     41.3±0.14ms        ? ?/sec    1.00     40.8±0.18ms        ? ?/sec
last_value merge_bench map<utf8,i64> nulls=0%                          1.01     39.8±0.12ms        ? ?/sec    1.00     39.6±0.14ms        ? ?/sec
last_value merge_bench map<utf8,i64> nulls=90%                         1.01     41.5±0.19ms        ? ?/sec    1.00     41.0±0.12ms        ? ?/sec
last_value merge_bench nulls=0%, filter=false                          1.00     34.8±0.09ms        ? ?/sec    1.01     35.0±0.08ms        ? ?/sec
last_value merge_bench nulls=0%, filter=true                           1.00     34.7±0.08ms        ? ?/sec    1.00     34.9±0.12ms        ? ?/sec
last_value merge_bench nulls=90%, filter=false                         1.01     46.4±0.08ms        ? ?/sec    1.00     45.8±0.09ms        ? ?/sec
last_value merge_bench nulls=90%, filter=true                          1.02     46.6±0.13ms        ? ?/sec    1.00     45.8±0.09ms        ? ?/sec
last_value merge_bench struct(i64,utf8,f64) nulls=0%                   1.01     39.7±0.08ms        ? ?/sec    1.00     39.5±0.08ms        ? ?/sec
last_value merge_bench struct(i64,utf8,f64) nulls=90%                  1.00     42.0±0.10ms        ? ?/sec    1.00     42.0±0.09ms        ? ?/sec
last_value trivial_update_bench nulls=0%, ignore_nulls=false           1.00      2.7±0.02µs        ? ?/sec    1.00      2.7±0.06µs        ? ?/sec
last_value trivial_update_bench nulls=0%, ignore_nulls=true            1.00      2.7±0.01µs        ? ?/sec    1.00      2.7±0.01µs        ? ?/sec
last_value trivial_update_bench nulls=90%, ignore_nulls=false          1.00      2.9±0.14µs        ? ?/sec    1.00      2.9±0.02µs        ? ?/sec
last_value trivial_update_bench nulls=90%, ignore_nulls=true           1.01      7.4±0.10µs        ? ?/sec    1.00      7.3±0.10µs        ? ?/sec
last_value update_bench list<i64>[4] nulls=0%                          1.00     32.5±0.11ms        ? ?/sec    1.01     32.7±0.07ms        ? ?/sec
last_value update_bench list<i64>[4] nulls=90%                         1.00     32.7±0.11ms        ? ?/sec    1.02     33.3±0.16ms        ? ?/sec
last_value update_bench list<struct(i64,utf8)>[4] nulls=0%             1.00     34.7±0.14ms        ? ?/sec    1.01     35.0±0.17ms        ? ?/sec
last_value update_bench list<struct(i64,utf8)>[4] nulls=90%            1.00     36.2±0.16ms        ? ?/sec    1.01     36.4±0.16ms        ? ?/sec
last_value update_bench map<utf8,i64> nulls=0%                         1.00     34.7±0.14ms        ? ?/sec    1.01     34.9±0.11ms        ? ?/sec
last_value update_bench map<utf8,i64> nulls=90%                        1.00     36.5±0.20ms        ? ?/sec    1.00     36.6±0.12ms        ? ?/sec
last_value update_bench nulls=0%, filter=false                         1.00     29.1±0.05ms        ? ?/sec    1.01     29.4±0.15ms        ? ?/sec
last_value update_bench nulls=0%, filter=true                          1.01     46.2±0.19ms        ? ?/sec    1.00     45.9±0.23ms        ? ?/sec
last_value update_bench nulls=90%, filter=false                        1.01     41.8±0.08ms        ? ?/sec    1.00     41.3±0.07ms        ? ?/sec
last_value update_bench nulls=90%, filter=true                         1.02     53.5±0.40ms        ? ?/sec    1.00     52.4±0.41ms        ? ?/sec
last_value update_bench struct(i64,utf8,f64) nulls=0%                  1.00     34.8±0.10ms        ? ?/sec    1.01     35.0±0.09ms        ? ?/sec
last_value update_bench struct(i64,utf8,f64) nulls=90%                 1.00     37.3±0.08ms        ? ?/sec    1.01     37.6±0.08ms        ? ?/sec

Resource Usage

first_last — base (merge-base)

Metric Value
Wall time 1160.3s
Peak memory 2.8 GiB
Avg memory 156.5 MiB
CPU user 1133.1s
CPU sys 8.2s
Peak spill 0 B

first_last — branch

Metric Value
Wall time 1140.3s
Peak memory 2.8 GiB
Avg memory 165.5 MiB
CPU user 1166.1s
CPU sys 8.9s
Peak spill 0 B

File an issue against this benchmark runner

#[expect(clippy::unit_arg)]
black_box(
acc.update_batch(
&[Arc::clone(values), Arc::clone(&ord)],

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.

Feeding the same ord array in to every iteration is a little unrealistic, no? That will measure comparison cost, but doesn't capture workloads where the winner changes over time and the aggregate's running value needs to be updated.

@zhuqi-lucas zhuqi-lucas Aug 21, 2026

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.

Thanks @neilconway for the review — good catch. You're right: reusing one ord meant iters 2..100 only hit compare-and-reject, so the update path wasn't measured.

Pushed a (winner changes) variant that feeds a strictly-decreasing ord per iteration, so every row becomes a new winner and the running value is replaced+copied every time — this exercises the update path (where the struct plan copies one wider row vs N narrow ones) that the reused-array version skipped. Kept the original as (winner stable) so both the compare-reject and compare-replace paths are covered. Will post fresh numbers once the bot reruns.

Adds coalesce_comparison_bench to the first_last benchmark: N independent
primitive first_value accumulators (the pre-rewrite plan) vs one struct-valued
accumulator carrying the same N columns (the post-rewrite plan produced by the
CoalesceFirstLast optimizer rule). The struct path uses the native nested
GroupsAccumulator from apache#23628.

Runs as 'first_value coalesce_peers(i64,utf8,f64) separate x3' vs
'... coalesced struct' so the head-to-head win is visible in the same run.

Part of apache#23600.
The existing coalesce-peers head-to-head reused one `ord` array every
iteration, so after the first iteration it only exercised compare-and-reject
(the pure ordering-comparison path). Add a `(winner changes)` variant that
feeds a strictly-decreasing `ord` per iteration, forcing the running value to
be replaced+copied on every row, and label the original `(winner stable)`.
This covers both the compare-reject and compare-replace paths, so the struct
plan's wider running-value copy is measured too, per review feedback.
@zhuqi-lucas
zhuqi-lucas force-pushed the bench/first-last-coalesce-peers branch from 58c0117 to 7b438cb Compare August 21, 2026 14:57
@zhuqi-lucas

Copy link
Copy Markdown
Contributor Author

run benchmark first_last

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5371558707-1841-z5xt5 6.12.85+ #1 SMP Sat Jun 27 09:31:30 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 bench/first-last-coalesce-peers (7b438cb) to 5f0ba13 (merge-base) diff

Run configuration
run benchmark first_last

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)

Comparing bench/first-last-coalesce-peers (7b438cb) to 5f0ba13 (merge-base) diff

Run configuration
run benchmark first_last
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

group                                                                         HEAD                                   bench_first-last-coalesce-peers
-----                                                                         ----                                   -------------------------------
first_value coalesce_peers(i64,utf8,f64) coalesced struct (winner changes)                                           1.00    421.4±7.76ms        ? ?/sec
first_value coalesce_peers(i64,utf8,f64) coalesced struct (winner stable)                                            1.00     34.3±0.10ms        ? ?/sec
first_value coalesce_peers(i64,utf8,f64) separate x3 (winner changes)                                                1.00     77.5±1.07ms        ? ?/sec
first_value coalesce_peers(i64,utf8,f64) separate x3 (winner stable)                                                 1.00     87.8±0.33ms        ? ?/sec
first_value evaluate_bench list<i64>[4] nulls=0%, all                         1.00   474.5±20.58µs        ? ?/sec    1.06   505.1±16.36µs        ? ?/sec
first_value evaluate_bench list<i64>[4] nulls=90%, all                        1.00    560.2±4.19µs        ? ?/sec    1.02   570.6±19.01µs        ? ?/sec
first_value evaluate_bench list<struct(i64,utf8)>[4] nulls=0%, all            1.00   1037.0±3.62µs        ? ?/sec    1.01  1046.7±37.06µs        ? ?/sec
first_value evaluate_bench list<struct(i64,utf8)>[4] nulls=90%, all           1.14  1122.7±53.02µs        ? ?/sec    1.00   986.6±23.44µs        ? ?/sec
first_value evaluate_bench map<utf8,i64> nulls=0%, all                        1.00   859.1±23.62µs        ? ?/sec    1.01   866.8±29.86µs        ? ?/sec
first_value evaluate_bench map<utf8,i64> nulls=90%, all                       1.00  1005.0±91.95µs        ? ?/sec    1.16  1167.8±62.86µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=false, all                        1.03     17.4±1.60µs        ? ?/sec    1.00     16.9±1.81µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=false, first(2)                   1.00     12.6±1.07µs        ? ?/sec    1.07     13.5±2.25µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=true, all                         1.01     16.6±2.06µs        ? ?/sec    1.00     16.5±1.72µs        ? ?/sec
first_value evaluate_bench nulls=0%, filter=true, first(2)                    1.14     20.3±2.76µs        ? ?/sec    1.00     17.8±1.61µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=false, all                       1.05     17.6±2.45µs        ? ?/sec    1.00     16.8±1.77µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=false, first(2)                  1.08     18.8±1.88µs        ? ?/sec    1.00     17.5±1.33µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=true, all                        1.10     17.8±2.23µs        ? ?/sec    1.00     16.2±1.17µs        ? ?/sec
first_value evaluate_bench nulls=90%, filter=true, first(2)                   1.02     17.6±1.53µs        ? ?/sec    1.00     17.3±0.94µs        ? ?/sec
first_value evaluate_bench struct(i64,utf8,f64) nulls=0%, all                 1.00   724.7±56.63µs        ? ?/sec    1.15   836.1±22.55µs        ? ?/sec
first_value evaluate_bench struct(i64,utf8,f64) nulls=90%, all                1.05   866.9±41.43µs        ? ?/sec    1.00   821.9±36.11µs        ? ?/sec
first_value merge_bench list<i64>[4] nulls=0%                                 1.00     37.3±0.13ms        ? ?/sec    1.00     37.2±0.16ms        ? ?/sec
first_value merge_bench list<i64>[4] nulls=90%                                1.00     37.6±0.17ms        ? ?/sec    1.00     37.5±0.17ms        ? ?/sec
first_value merge_bench list<struct(i64,utf8)>[4] nulls=0%                    1.01     39.4±0.22ms        ? ?/sec    1.00     39.2±0.13ms        ? ?/sec
first_value merge_bench list<struct(i64,utf8)>[4] nulls=90%                   1.00     40.4±0.25ms        ? ?/sec    1.01     40.7±0.31ms        ? ?/sec
first_value merge_bench map<utf8,i64> nulls=0%                                1.01     39.7±0.33ms        ? ?/sec    1.00     39.5±0.23ms        ? ?/sec
first_value merge_bench map<utf8,i64> nulls=90%                               1.01     41.2±3.33ms        ? ?/sec    1.00     40.9±0.45ms        ? ?/sec
first_value merge_bench nulls=0%, filter=false                                1.00     35.1±0.06ms        ? ?/sec    1.00     35.0±0.15ms        ? ?/sec
first_value merge_bench nulls=0%, filter=true                                 1.00     35.2±0.09ms        ? ?/sec    1.00     35.1±0.08ms        ? ?/sec
first_value merge_bench nulls=90%, filter=false                               1.00     38.0±0.06ms        ? ?/sec    1.00     37.9±0.06ms        ? ?/sec
first_value merge_bench nulls=90%, filter=true                                1.00     37.9±0.09ms        ? ?/sec    1.00     37.8±0.09ms        ? ?/sec
first_value merge_bench struct(i64,utf8,f64) nulls=0%                         1.00     39.6±0.20ms        ? ?/sec    1.00     39.4±0.20ms        ? ?/sec
first_value merge_bench struct(i64,utf8,f64) nulls=90%                        1.00     41.8±0.23ms        ? ?/sec    1.00     41.9±0.24ms        ? ?/sec
first_value trivial_update_bench nulls=0%, ignore_nulls=false                 1.00      2.6±0.07µs        ? ?/sec    1.01      2.6±0.09µs        ? ?/sec
first_value trivial_update_bench nulls=0%, ignore_nulls=true                  1.00      2.6±0.07µs        ? ?/sec    1.00      2.6±0.12µs        ? ?/sec
first_value trivial_update_bench nulls=90%, ignore_nulls=false                1.00      2.9±0.17µs        ? ?/sec    1.01      2.9±0.11µs        ? ?/sec
first_value trivial_update_bench nulls=90%, ignore_nulls=true                 1.00      3.6±0.02µs        ? ?/sec    1.00      3.6±0.03µs        ? ?/sec
first_value update_bench list<i64>[4] nulls=0%                                1.00     31.8±0.10ms        ? ?/sec    1.00     32.0±0.16ms        ? ?/sec
first_value update_bench list<i64>[4] nulls=90%                               1.01     32.6±0.16ms        ? ?/sec    1.00     32.4±0.14ms        ? ?/sec
first_value update_bench list<struct(i64,utf8)>[4] nulls=0%                   1.00     34.3±0.30ms        ? ?/sec    1.00     34.1±0.18ms        ? ?/sec
first_value update_bench list<struct(i64,utf8)>[4] nulls=90%                  1.00     35.5±0.29ms        ? ?/sec    1.00     35.4±0.16ms        ? ?/sec
first_value update_bench map<utf8,i64> nulls=0%                               1.00     34.1±0.15ms        ? ?/sec    1.00     34.2±0.19ms        ? ?/sec
first_value update_bench map<utf8,i64> nulls=90%                              1.02     36.5±0.26ms        ? ?/sec    1.00     35.8±0.24ms        ? ?/sec
first_value update_bench nulls=0%, filter=false                               1.00     29.3±0.07ms        ? ?/sec    1.00     29.3±0.07ms        ? ?/sec
first_value update_bench nulls=0%, filter=true                                1.00     46.4±0.23ms        ? ?/sec    1.00     46.4±0.24ms        ? ?/sec
first_value update_bench nulls=90%, filter=false                              1.00     32.9±0.07ms        ? ?/sec    1.00     32.9±0.13ms        ? ?/sec
first_value update_bench nulls=90%, filter=true                               1.00     46.6±0.35ms        ? ?/sec    1.00     46.4±0.31ms        ? ?/sec
first_value update_bench struct(i64,utf8,f64) nulls=0%                        1.00     34.5±0.12ms        ? ?/sec    1.00     34.6±0.20ms        ? ?/sec
first_value update_bench struct(i64,utf8,f64) nulls=90%                       1.01     37.2±0.15ms        ? ?/sec    1.00     37.0±0.21ms        ? ?/sec
last_value evaluate_bench nulls=0%, filter=false, all                         1.02     17.4±2.30µs        ? ?/sec    1.00     17.1±1.68µs        ? ?/sec
last_value evaluate_bench nulls=0%, filter=false, first(2)                    1.16     20.8±2.51µs        ? ?/sec    1.00     17.9±1.73µs        ? ?/sec
last_value evaluate_bench nulls=0%, filter=true, all                          1.00     16.4±1.46µs        ? ?/sec    1.07     17.5±2.42µs        ? ?/sec
last_value evaluate_bench nulls=0%, filter=true, first(2)                     1.00     18.1±1.60µs        ? ?/sec    1.14     20.7±2.82µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=false, all                        1.09     18.7±2.18µs        ? ?/sec    1.00     17.2±1.83µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=false, first(2)                   1.00     17.3±0.65µs        ? ?/sec    1.09     18.9±2.56µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=true, all                         1.00     16.8±1.72µs        ? ?/sec    1.01     16.9±2.09µs        ? ?/sec
last_value evaluate_bench nulls=90%, filter=true, first(2)                    1.00     18.7±2.45µs        ? ?/sec    1.08     20.1±2.20µs        ? ?/sec
last_value merge_bench list<i64>[4] nulls=0%                                  1.00     37.5±0.15ms        ? ?/sec    1.00     37.5±0.11ms        ? ?/sec
last_value merge_bench list<i64>[4] nulls=90%                                 1.00     38.0±0.20ms        ? ?/sec    1.00     38.1±0.14ms        ? ?/sec
last_value merge_bench list<struct(i64,utf8)>[4] nulls=0%                     1.00     39.9±0.20ms        ? ?/sec    1.00     40.0±0.31ms        ? ?/sec
last_value merge_bench list<struct(i64,utf8)>[4] nulls=90%                    1.00     40.9±0.18ms        ? ?/sec    1.02     41.7±0.39ms        ? ?/sec
last_value merge_bench map<utf8,i64> nulls=0%                                 1.00     39.6±0.17ms        ? ?/sec    1.01     39.8±0.36ms        ? ?/sec
last_value merge_bench map<utf8,i64> nulls=90%                                1.00     41.3±0.21ms        ? ?/sec    1.01     41.5±0.34ms        ? ?/sec
last_value merge_bench nulls=0%, filter=false                                 1.01     35.2±0.10ms        ? ?/sec    1.00     34.9±0.16ms        ? ?/sec
last_value merge_bench nulls=0%, filter=true                                  1.01     35.2±0.11ms        ? ?/sec    1.00     34.9±0.07ms        ? ?/sec
last_value merge_bench nulls=90%, filter=false                                1.00     44.9±0.10ms        ? ?/sec    1.01     45.2±0.10ms        ? ?/sec
last_value merge_bench nulls=90%, filter=true                                 1.00     44.9±0.13ms        ? ?/sec    1.01     45.3±0.12ms        ? ?/sec
last_value merge_bench struct(i64,utf8,f64) nulls=0%                          1.01     40.0±0.15ms        ? ?/sec    1.00     39.7±0.14ms        ? ?/sec
last_value merge_bench struct(i64,utf8,f64) nulls=90%                         1.00     42.3±0.22ms        ? ?/sec    1.01     42.5±0.25ms        ? ?/sec
last_value trivial_update_bench nulls=0%, ignore_nulls=false                  1.00      2.7±0.02µs        ? ?/sec    1.00      2.7±0.02µs        ? ?/sec
last_value trivial_update_bench nulls=0%, ignore_nulls=true                   1.00      2.7±0.02µs        ? ?/sec    1.02      2.7±0.02µs        ? ?/sec
last_value trivial_update_bench nulls=90%, ignore_nulls=false                 1.00      2.9±0.03µs        ? ?/sec    1.00      2.9±0.17µs        ? ?/sec
last_value trivial_update_bench nulls=90%, ignore_nulls=true                  1.00      7.4±0.05µs        ? ?/sec    1.00      7.4±0.07µs        ? ?/sec
last_value update_bench list<i64>[4] nulls=0%                                 1.00     32.4±0.15ms        ? ?/sec    1.00     32.3±0.13ms        ? ?/sec
last_value update_bench list<i64>[4] nulls=90%                                1.00     32.7±0.15ms        ? ?/sec    1.00     32.8±0.13ms        ? ?/sec
last_value update_bench list<struct(i64,utf8)>[4] nulls=0%                    1.00     34.6±0.16ms        ? ?/sec    1.00     34.5±0.14ms        ? ?/sec
last_value update_bench list<struct(i64,utf8)>[4] nulls=90%                   1.00     35.8±0.24ms        ? ?/sec    1.00     35.8±0.23ms        ? ?/sec
last_value update_bench map<utf8,i64> nulls=0%                                1.00     34.6±0.14ms        ? ?/sec    1.00     34.4±0.29ms        ? ?/sec
last_value update_bench map<utf8,i64> nulls=90%                               1.00     36.0±0.14ms        ? ?/sec    1.00     36.1±0.12ms        ? ?/sec
last_value update_bench nulls=0%, filter=false                                1.00     29.2±0.06ms        ? ?/sec    1.00     29.2±0.20ms        ? ?/sec
last_value update_bench nulls=0%, filter=true                                 1.00     46.4±0.21ms        ? ?/sec    1.00     46.3±0.24ms        ? ?/sec
last_value update_bench nulls=90%, filter=false                               1.00     40.7±0.14ms        ? ?/sec    1.00     40.7±0.19ms        ? ?/sec
last_value update_bench nulls=90%, filter=true                                1.01     52.2±0.43ms        ? ?/sec    1.00     51.9±0.36ms        ? ?/sec
last_value update_bench struct(i64,utf8,f64) nulls=0%                         1.00     34.8±0.12ms        ? ?/sec    1.00     34.7±0.19ms        ? ?/sec
last_value update_bench struct(i64,utf8,f64) nulls=90%                        1.00     37.2±0.10ms        ? ?/sec    1.00     37.1±0.12ms        ? ?/sec

Resource Usage

first_last — base (merge-base)

Metric Value
Wall time 1230.3s
Peak memory 2.8 GiB
Avg memory 150.8 MiB
CPU user 1132.4s
CPU sys 8.1s
Peak spill 0 B

first_last — branch

Metric Value
Wall time 1300.3s
Peak memory 2.8 GiB
Avg memory 147.4 MiB
CPU user 1219.2s
CPU sys 8.9s
Peak spill 0 B

File an issue against this benchmark runner

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

functions Changes to functions implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants