Skip to content

fix: charge retained scratch indices capacity in GroupsAccumulatorAdapter - #24858

Open
adriangb wants to merge 2 commits into
mainfrom
claude/groups-accumulator-indices-accounting
Open

fix: charge retained scratch indices capacity in GroupsAccumulatorAdapter#24858
adriangb wants to merge 2 commits into
mainfrom
claude/groups-accumulator-indices-accounting

Conversation

@adriangb

@adriangb adriangb commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

GroupsAccumulatorAdapter never charges the capacity of its scratch indices vector to the MemoryPool. An aggregate holds megabytes that the pool does not see, so a memory limit does not stop it.

Reproduction

This needs only datafusion-cli. There is no patch, no custom allocator and no data file.

-- repro.sql
SET datafusion.execution.target_partitions = 1;
SET datafusion.execution.batch_size = 8192;
EXPLAIN ANALYZE
SELECT v / 8192 AS g, covar_samp(v, v) AS c
FROM generate_series(0, 1048575) AS t(v)
GROUP BY v / 8192;
datafusion-cli -m 1M -f repro.sql

covar_samp has no specialized GroupsAccumulator, so it runs through GroupsAccumulatorAdapter. The query makes 128 groups. Each group gets one full 8192-row batch. The scratch vectors hold 128 * 8192 * 4 bytes, which is 4 MiB against a 1 MiB limit.

Merge base da89c7c85b. The aggregate runs past the limit and does not spill:

AggregateExec: mode=Single, gby=[v@1 / 8192 as t.v / Int64(8192)], aggr=[covar_samp(t.v,t.v)],
metrics=[output_rows=128, elapsed_compute=14.48ms, output_bytes=2.0 KB, output_batches=1,
spill_count=0, spilled_bytes=0.0 B, spilled_rows=0, ...]

This branch. The aggregate sees the same bytes and spills:

AggregateExec: mode=Single, gby=[v@1 / 8192 as t.v / Int64(8192)], aggr=[covar_samp(t.v,t.v)],
metrics=[output_rows=128, elapsed_compute=15.02ms, output_bytes=2.0 KB, output_batches=2,
spill_count=5, spilled_bytes=9.2 KB, spilled_rows=128, ...]
merge base da89c7c85b this branch
spill_count 0 5
spilled_bytes 0.0 B 9.2 KB
spilled_rows 0 128

The query returns the same 128 rows on both builds. The run takes under a second. Both numbers repeat exactly across runs.

target_partitions = 1 makes the effect visible. The planner then folds the aggregate into one AggregateMode::Single node, which spills. An AggregateMode::Partial node uses OutOfMemoryMode::EmitEarly and sheds the bytes instead.

Which issue does this PR close?

No existing issue. I found this when I investigated a production out of memory. I can file an issue if you want it in the changelog.

Rationale for this change

The adapter keeps a running total in allocation_bytes. It measures AccumulatorState::size() before and after the accumulator work, then charges the difference.

The scratch vector grows in the per-row push loop. That loop runs before the adapter measures sizes_pre. The indices.clear() call after the work keeps the capacity. Both measurements therefore see the same capacity, the difference is always zero, and the adapter never charges the capacity.

evaluate and state have the opposite error. Both call free_allocation(state.size()) and release a capacity that the adapter never charged. allocation_bytes thus falls to zero across the partial emits.

The size of the hole is groups * rows_per_batch * 4 bytes.

How large the error is

An instrumented allocator measured these numbers, so the CLI cannot reproduce them. A counting GlobalAlloc gives the heap that the query holds. A peak-recording MemoryPool gives the reported bytes.

groups heap held reported, base error reported, this branch error
512 17,197,804 145,408 99.15% 16,922,624 1.60%
4,096 135,061,228 704,512 99.48% 134,922,240 0.10%

The peak heap agrees between the two builds to within 8 bytes. The memory use does not change. Only the reported number moves.

What changes are included in this PR?

A new private field indices_allocation_bytes records the capacity that the adapter already charged. Each batch totals the current capacity in the loop that already visits every group, then charges only the growth. An emit removes the capacity of the emitted state from that total.

This adds no size() call and no per-row work. It adds one usize addition per group per batch to an existing loop.

The invariant is allocation_bytes == sum(state.size()) + states.allocated_size(). Four new tests assert it against an oracle that they recompute from the states. All four fail on da89c7c85b and pass here.

Are there any user-facing changes?

No public API change and no change to query results. Only the accounting arithmetic changes.

A memory-limited aggregate now reports its true size to the MemoryPool. It can therefore spill, or fail where it cannot spill, in cases where it previously ran past its limit.

A note on metrics

grouped_hash_stream.rs records a peak_mem_used gauge from the pool reservation. That gauge is the exact number this PR corrects. EXPLAIN ANALYZE does not print it, and EXPLAIN ANALYZE VERBOSE does not print it either. The reproduction above therefore uses spill_count under a fixed limit. If the aggregate exposed peak_mem_used, a reviewer could see this bug with no memory limit at all.

…dapter

`GroupsAccumulatorAdapter` tracks per-group memory in `allocation_bytes` by
measuring each `AccumulatorState::size()` before and after accumulator work and
applying the delta. `size()` includes the scratch `indices` vector's capacity,
but that capacity is never charged, because:

1. `indices` grows in the per-row push loop, which runs before `sizes_pre` is
   measured;
2. `indices.clear()` after the accumulator call retains the capacity.

So `sizes_pre` and `sizes_post` observe the identical `allocated_size()` on
every batch and the delta is always zero. The capacity is charged exactly zero
times, permanently, while `size()` is what the aggregate stream reports to the
`MemoryPool`, so the pool under-counts and memory-pressure handling is delayed.

The same asymmetry has a second effect at emit time: `evaluate` and `state`
call `free_allocation(state.size())`, which releases capacity that was never
charged, so `allocation_bytes` drifts down (and saturates at zero) across
partial emits.

Charge the growth explicitly. `indices_allocation_bytes` records the capacity
already charged; each batch totals the current capacity in the pass that
already visits every group and charges only the difference, so a group whose
`indices` grew once and was then cleared stays charged without being charged
again. Emitting a state drops its capacity from that total. The invariant is
now that `allocation_bytes` equals the sum of `AccumulatorState::size()` plus
the `states` vector allocation, which is what the added tests assert.

No new per-row work: the push loop is untouched, and no `size()` call is added
(`size()` was historically a bottleneck with many distinct groups, which is why
deltas are used). The added cost is one `usize` addition per group per batch in
an existing loop.

Measured on a 16384-row batch across 1000 groups, with 8192 rows in group 0 and
the rest spread evenly over the remaining 999, using a 16-byte accumulator:
168,096 bytes truly retained, 96,960 reported before, so 71,136 bytes (42%) went
unaccounted. Query results are unchanged.
@github-actions github-actions Bot added the functions Changes to functions implementation label Sep 1, 2026
@codecov-commenter

codecov-commenter commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.90110% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 81.92%. Comparing base (da89c7c) to head (c67dafd).
⚠️ Report is 17 commits behind head on main.

Files with missing lines Patch % Lines
...gregate-common/src/aggregate/groups_accumulator.rs 98.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24858      +/-   ##
==========================================
+ Coverage   81.60%   81.92%   +0.32%     
==========================================
  Files        1123     1123              
  Lines      408898   414792    +5894     
  Branches   408898   414792    +5894     
==========================================
+ Hits       333670   339833    +6163     
+ Misses      55625    55502     -123     
+ Partials    19603    19457     -146     

☔ 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.

@adriangb

adriangb commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

run benchmark clickbench_partitioned external_aggr
env:
DATAFUSION_RUNTIME_MEMORY_LIMIT: 4G

@adriangb

adriangb commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

run benchmark clickbench_extended
env:
DATAFUSION_RUNTIME_MEMORY_LIMIT: 4G

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5500225377-2069-6n47c 6.12.94+ #1 SMP Fri Jul 17 09:42:57 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 claude/groups-accumulator-indices-accounting (6b5b27b) to da89c7c (merge-base) diff

Run configuration
run benchmark external_aggr
env:
  DATAFUSION_RUNTIME_MEMORY_LIMIT: "4G"

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-c5500225377-2068-cwk4w 6.12.94+ #1 SMP Fri Jul 17 09:42:57 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 claude/groups-accumulator-indices-accounting (6b5b27b) to da89c7c (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
env:
  DATAFUSION_RUNTIME_MEMORY_LIMIT: "4G"

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 claude/groups-accumulator-indices-accounting (6b5b27b) to da89c7c (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
env:
  DATAFUSION_RUNTIME_MEMORY_LIMIT: "4G"
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 claude_groups-accumulator-indices-accounting
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ claude_groups-accumulator-indices-accounting ┃       Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ QQuery 0  │    1.26 ms │                                      1.24 ms │    no change │
│ QQuery 1  │   11.96 ms │                                     12.11 ms │    no change │
│ QQuery 2  │   37.64 ms │                                     37.87 ms │    no change │
│ QQuery 3  │   31.94 ms │                                     32.34 ms │    no change │
│ QQuery 4  │  235.87 ms │                                    247.78 ms │ 1.05x slower │
│ QQuery 5  │  285.71 ms │                                    290.36 ms │    no change │
│ QQuery 6  │    1.29 ms │                                      1.30 ms │    no change │
│ QQuery 7  │   14.07 ms │                                     14.13 ms │    no change │
│ QQuery 8  │  357.23 ms │                                    366.15 ms │    no change │
│ QQuery 9  │  490.04 ms │                                    511.53 ms │    no change │
│ QQuery 10 │   74.26 ms │                                     73.70 ms │    no change │
│ QQuery 11 │   85.22 ms │                                     85.02 ms │    no change │
│ QQuery 12 │  289.13 ms │                                    295.51 ms │    no change │
│ QQuery 13 │ 1030.63 ms │                                   1050.88 ms │    no change │
│ QQuery 14 │  308.61 ms │                                    315.69 ms │    no change │
│ QQuery 15 │  291.74 ms │                                    301.24 ms │    no change │
│ QQuery 16 │ 1252.86 ms │                                   1320.89 ms │ 1.05x slower │
│ QQuery 17 │  941.23 ms │                                    982.92 ms │    no change │
│ QQuery 18 │ 2599.97 ms │                                   2638.60 ms │    no change │
│ QQuery 19 │   29.33 ms │                                     30.29 ms │    no change │
│ QQuery 20 │  537.12 ms │                                    541.05 ms │    no change │
│ QQuery 21 │  533.19 ms │                                    532.39 ms │    no change │
│ QQuery 22 │ 1013.39 ms │                                   1027.05 ms │    no change │
│ QQuery 23 │ 3171.71 ms │                                   3198.99 ms │    no change │
│ QQuery 24 │   42.82 ms │                                     43.95 ms │    no change │
│ QQuery 25 │  116.62 ms │                                    115.67 ms │    no change │
│ QQuery 26 │   44.33 ms │                                     43.74 ms │    no change │
│ QQuery 27 │  538.46 ms │                                    534.15 ms │    no change │
│ QQuery 28 │ 3015.74 ms │                                   3007.83 ms │    no change │
│ QQuery 29 │   42.39 ms │                                     42.40 ms │    no change │
│ QQuery 30 │  328.82 ms │                                    331.14 ms │    no change │
│ QQuery 31 │  302.50 ms │                                    302.89 ms │    no change │
│ QQuery 32 │ 3490.27 ms │                                   3490.47 ms │    no change │
│ QQuery 33 │ 2736.21 ms │                                   2746.29 ms │    no change │
│ QQuery 34 │ 2807.62 ms │                                   2865.29 ms │    no change │
│ QQuery 35 │  318.07 ms │                                    330.40 ms │    no change │
│ QQuery 36 │   69.16 ms │                                     71.08 ms │    no change │
│ QQuery 37 │   36.90 ms │                                     37.88 ms │    no change │
│ QQuery 38 │   41.50 ms │                                     44.39 ms │ 1.07x slower │
│ QQuery 39 │  141.70 ms │                                    139.85 ms │    no change │
│ QQuery 40 │   15.22 ms │                                     14.77 ms │    no change │
│ QQuery 41 │   14.87 ms │                                     14.49 ms │    no change │
│ QQuery 42 │   14.41 ms │                                     14.25 ms │    no change │
└───────────┴────────────┴──────────────────────────────────────────────┴──────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                                           ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                                           │ 27743.00ms │
│ Total Time (claude_groups-accumulator-indices-accounting)   │ 28099.94ms │
│ Average Time (HEAD)                                         │   645.19ms │
│ Average Time (claude_groups-accumulator-indices-accounting) │   653.49ms │
│ Queries Faster                                              │          0 │
│ Queries Slower                                              │          3 │
│ Queries with No Change                                      │         40 │
│ Queries with Failure                                        │          0 │
└─────────────────────────────────────────────────────────────┴────────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and claude_groups-accumulator-indices-accounting
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                  HEAD ┃ claude_groups-accumulator-indices-accounting ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │          1.26 / 4.16 ±5.66 / 15.47 ms │                 1.24 / 4.13 ±5.61 / 15.34 ms │     no change │
│ QQuery 1  │        11.96 / 12.44 ±0.30 / 12.78 ms │               12.11 / 12.41 ±0.15 / 12.53 ms │     no change │
│ QQuery 2  │        37.64 / 37.91 ±0.18 / 38.16 ms │               37.87 / 38.16 ±0.26 / 38.62 ms │     no change │
│ QQuery 3  │        31.94 / 32.39 ±0.55 / 33.41 ms │               32.34 / 32.67 ±0.34 / 33.33 ms │     no change │
│ QQuery 4  │     235.87 / 242.55 ±5.06 / 248.79 ms │            247.78 / 249.98 ±2.19 / 252.84 ms │     no change │
│ QQuery 5  │     285.71 / 294.40 ±5.03 / 299.48 ms │            290.36 / 295.06 ±2.73 / 298.76 ms │     no change │
│ QQuery 6  │           1.29 / 1.45 ±0.24 / 1.91 ms │                  1.30 / 1.45 ±0.23 / 1.91 ms │     no change │
│ QQuery 7  │        14.07 / 14.73 ±0.96 / 16.62 ms │               14.13 / 14.27 ±0.11 / 14.47 ms │     no change │
│ QQuery 8  │     357.23 / 365.78 ±6.61 / 374.97 ms │            366.15 / 371.60 ±4.19 / 378.13 ms │     no change │
│ QQuery 9  │    490.04 / 507.69 ±11.66 / 523.79 ms │            511.53 / 525.35 ±8.67 / 538.64 ms │     no change │
│ QQuery 10 │        74.26 / 78.33 ±7.33 / 92.99 ms │               73.70 / 74.96 ±0.70 / 75.68 ms │     no change │
│ QQuery 11 │        85.22 / 85.97 ±0.81 / 87.53 ms │               85.02 / 86.38 ±1.33 / 88.66 ms │     no change │
│ QQuery 12 │     289.13 / 299.45 ±7.68 / 311.18 ms │            295.51 / 303.12 ±6.97 / 311.95 ms │     no change │
│ QQuery 13 │ 1030.63 / 1053.88 ±18.63 / 1084.91 ms │         1050.88 / 1066.61 ±8.13 / 1073.41 ms │     no change │
│ QQuery 14 │     308.61 / 316.67 ±4.54 / 322.72 ms │           315.69 / 327.89 ±16.30 / 360.14 ms │     no change │
│ QQuery 15 │     291.74 / 297.48 ±3.81 / 302.11 ms │            301.24 / 306.30 ±3.41 / 310.42 ms │     no change │
│ QQuery 16 │ 1252.86 / 1271.14 ±14.46 / 1288.68 ms │        1320.89 / 1345.28 ±21.94 / 1374.82 ms │  1.06x slower │
│ QQuery 17 │   941.23 / 969.18 ±19.92 / 1002.46 ms │          982.92 / 996.47 ±14.78 / 1022.95 ms │     no change │
│ QQuery 18 │ 2599.97 / 2651.76 ±59.35 / 2735.17 ms │        2638.60 / 2711.02 ±49.46 / 2767.56 ms │     no change │
│ QQuery 19 │        29.33 / 29.83 ±0.57 / 30.90 ms │               30.29 / 31.13 ±1.40 / 33.92 ms │     no change │
│ QQuery 20 │     537.12 / 547.11 ±8.61 / 559.66 ms │            541.05 / 546.80 ±4.11 / 551.42 ms │     no change │
│ QQuery 21 │     533.19 / 540.23 ±7.80 / 555.45 ms │            532.39 / 536.59 ±3.10 / 542.03 ms │     no change │
│ QQuery 22 │ 1013.39 / 1032.88 ±14.08 / 1053.65 ms │        1027.05 / 1044.68 ±16.13 / 1067.82 ms │     no change │
│ QQuery 23 │ 3171.71 / 3226.27 ±32.18 / 3263.97 ms │        3198.99 / 3214.34 ±19.46 / 3252.21 ms │     no change │
│ QQuery 24 │        42.82 / 43.84 ±0.73 / 44.65 ms │               43.95 / 46.59 ±4.57 / 55.69 ms │  1.06x slower │
│ QQuery 25 │    116.62 / 123.25 ±11.38 / 145.92 ms │           115.67 / 128.39 ±13.98 / 147.47 ms │     no change │
│ QQuery 26 │        44.33 / 46.46 ±2.92 / 52.06 ms │               43.74 / 46.98 ±4.55 / 55.89 ms │     no change │
│ QQuery 27 │     538.46 / 545.72 ±6.50 / 556.56 ms │            534.15 / 536.50 ±1.89 / 538.79 ms │     no change │
│ QQuery 28 │ 3015.74 / 3050.58 ±24.82 / 3086.67 ms │        3007.83 / 3053.69 ±29.94 / 3084.50 ms │     no change │
│ QQuery 29 │        42.39 / 42.67 ±0.19 / 42.92 ms │               42.40 / 42.80 ±0.42 / 43.41 ms │     no change │
│ QQuery 30 │    328.82 / 345.71 ±17.11 / 373.23 ms │            331.14 / 336.13 ±3.98 / 340.72 ms │     no change │
│ QQuery 31 │     302.50 / 310.58 ±8.30 / 324.52 ms │            302.89 / 311.01 ±6.21 / 320.45 ms │     no change │
│ QQuery 32 │ 3490.27 / 3558.31 ±35.31 / 3585.22 ms │        3490.47 / 3526.90 ±30.96 / 3567.47 ms │     no change │
│ QQuery 33 │ 2736.21 / 2770.39 ±33.80 / 2834.32 ms │       2746.29 / 2953.63 ±140.37 / 3163.38 ms │  1.07x slower │
│ QQuery 34 │ 2807.62 / 2856.51 ±43.72 / 2920.45 ms │        2865.29 / 2935.51 ±60.66 / 3011.92 ms │     no change │
│ QQuery 35 │     318.07 / 327.62 ±6.93 / 336.14 ms │           330.40 / 346.99 ±15.08 / 366.61 ms │  1.06x slower │
│ QQuery 36 │        69.16 / 72.07 ±3.93 / 79.69 ms │               71.08 / 74.31 ±2.74 / 79.07 ms │     no change │
│ QQuery 37 │        36.90 / 37.54 ±0.86 / 39.22 ms │              37.88 / 49.77 ±22.68 / 95.12 ms │  1.33x slower │
│ QQuery 38 │        41.50 / 46.00 ±6.64 / 58.84 ms │               44.39 / 48.10 ±3.90 / 53.88 ms │     no change │
│ QQuery 39 │    141.70 / 152.84 ±13.71 / 177.04 ms │            139.85 / 148.28 ±7.40 / 159.64 ms │     no change │
│ QQuery 40 │        15.22 / 16.00 ±1.00 / 17.90 ms │               14.77 / 15.35 ±0.31 / 15.63 ms │     no change │
│ QQuery 41 │        14.87 / 16.51 ±2.21 / 20.83 ms │               14.49 / 14.72 ±0.18 / 14.96 ms │ +1.12x faster │
│ QQuery 42 │        14.41 / 14.79 ±0.20 / 14.95 ms │               14.25 / 17.11 ±4.55 / 26.05 ms │  1.16x slower │
└───────────┴───────────────────────────────────────┴──────────────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                                           ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                                           │ 28291.09ms │
│ Total Time (claude_groups-accumulator-indices-accounting)   │ 28769.44ms │
│ Average Time (HEAD)                                         │   657.93ms │
│ Average Time (claude_groups-accumulator-indices-accounting) │   669.06ms │
│ Queries Faster                                              │          1 │
│ Queries Slower                                              │          6 │
│ Queries with No Change                                      │         36 │
│ Queries with Failure                                        │          0 │
└─────────────────────────────────────────────────────────────┴────────────┘

Memory Pool Peaks

Peak MemoryPool reservation per query — what DataFusion's accounting believes it reserved. Recorded only when the benchmark runs with DATAFUSION_RUNTIME_MEMORY_LIMIT set.

Base: da89c7c (merge-base) | Changed: claude/groups-accumulator-indices-accounting

clickbench_partitioned

Query Base Changed Change
Query 0 0 B 0 B 0.0%
Query 1 104 B 104 B +0.0%
Query 2 936 B 936 B +0.0%
Query 3 312 B 312 B +0.0%
Query 4 771.1 MiB 771.0 MiB -0.0%
Query 5 1.2 GiB 1.1 GiB -3.0%
Query 6 0 B 0 B 0.0%
Query 7 60.1 MiB 40.2 MiB -33.0%
Query 8 870.8 MiB 871.5 MiB +0.1%
Query 9 551.7 MiB 593.9 MiB +7.6%
Query 10 114.3 MiB 111.7 MiB -2.3%
Query 11 116.5 MiB 107.1 MiB -8.1%
Query 12 1.3 GiB 1.3 GiB +1.0%
Query 13 1.0 GiB 1.0 GiB +2.7%
Query 14 1.3 GiB 1.3 GiB +2.1%
Query 15 1.2 GiB 1.1 GiB -4.8%
Query 16 1.9 GiB 2.0 GiB +6.3%
Query 17 2.0 GiB 1.8 GiB -9.3%
Query 18 2.0 GiB 2.2 GiB +13.8%
Query 19 0 B 0 B 0.0%
Query 20 104 B 104 B +0.0%
Query 21 3.6 MiB 3.3 MiB -9.5%
Query 22 4.4 MiB 3.6 MiB -17.3%
Query 23 26.5 MiB 30.4 MiB +14.6%
Query 24 60.6 MiB 59.3 MiB -2.1%
Query 25 174.3 MiB 181.2 MiB +3.9%
Query 26 61.3 MiB 60.2 MiB -1.9%
Query 27 2.4 MiB 2.5 MiB +2.8%
Query 28 1.5 GiB 1.6 GiB +2.9%
Query 29 624 B 624 B +0.0%
Query 30 719.0 MiB 689.2 MiB -4.1%
Query 31 1.6 GiB 1.5 GiB -5.8%
Query 32 928.2 MiB 925.5 MiB -0.3%
Query 33 2.2 GiB 2.0 GiB -5.5%
Query 34 2.0 GiB 2.1 GiB +4.5%
Query 35 611.8 MiB 597.8 MiB -2.3%
Query 36 111.9 MiB 112.3 MiB +0.4%
Query 37 6.9 MiB 6.3 MiB -9.1%
Query 38 5.2 MiB 5.3 MiB +2.1%
Query 39 297.8 MiB 298.1 MiB +0.1%
Query 40 1.7 MiB 2.0 MiB +17.1%
Query 41 3.1 MiB 3.1 MiB +0.0%
Query 42 1.7 MiB 1.8 MiB +12.0%

Pool accounting vs. process RSS

Max pool peak is the largest reservation any single query in the run reached; peak RSS covers the whole invocation, including data loading and allocator retention, and the two high-water marks need not coincide in time. The gap is therefore an upper bound on what the pool did not account for, not a measurement of it.

Benchmark Side Max pool peak Peak RSS Gap RSS / pool
clickbench_partitioned base (da89c7c (merge-base)) 2.2 GiB 8.3 GiB 6.1 GiB 3.8×
clickbench_partitioned changed (claude/groups-accumulator-indices-accounting) 2.2 GiB 8.6 GiB 6.4 GiB 3.9×
Resource Usage

clickbench_partitioned — base (merge-base)

Metric Value
Wall time 145.0s
Peak memory 8.3 GiB
Avg memory 5.2 GiB
CPU user 1437.3s
CPU sys 143.3s
Peak spill 0 B

clickbench_partitioned — branch

Metric Value
Wall time 145.0s
Peak memory 8.6 GiB
Avg memory 5.5 GiB
CPU user 1449.1s
CPU sys 147.0s
Peak spill 0 B

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-c5500235531-2074-6vwdl 6.12.94+ #1 SMP Fri Jul 17 09:42:57 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 claude/groups-accumulator-indices-accounting (6b5b27b) to da89c7c (merge-base) diff

Run configuration
run benchmark clickbench_extended
env:
  DATAFUSION_RUNTIME_MEMORY_LIMIT: "4G"

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 claude/groups-accumulator-indices-accounting (6b5b27b) to da89c7c (merge-base) diff

Run configuration
run benchmark external_aggr
env:
  DATAFUSION_RUNTIME_MEMORY_LIMIT: "4G"
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 claude_groups-accumulator-indices-accounting
--------------------
Benchmark external_aggr.json
--------------------
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query        ┃      HEAD ┃ claude_groups-accumulator-indices-accounting ┃    Change ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Q1(64.0 MB)  │  51.55 ms │                                     52.52 ms │ no change │
│ Q1(32.0 MB)  │  49.47 ms │                                     50.82 ms │ no change │
│ Q1(16.0 MB)  │  46.61 ms │                                     47.95 ms │ no change │
│ Q2(512.0 MB) │ 277.91 ms │                                    277.59 ms │ no change │
│ Q2(256.0 MB) │ 270.02 ms │                                    270.41 ms │ no change │
│ Q2(128.0 MB) │ 242.78 ms │                                    244.49 ms │ no change │
│ Q2(64.0 MB)  │ 242.33 ms │                                    242.95 ms │ no change │
│ Q2(32.0 MB)  │ 304.96 ms │                                    300.99 ms │ no change │
└──────────────┴───────────┴──────────────────────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                                           ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD)                                           │ 1485.63ms │
│ Total Time (claude_groups-accumulator-indices-accounting)   │ 1487.73ms │
│ Average Time (HEAD)                                         │  185.70ms │
│ Average Time (claude_groups-accumulator-indices-accounting) │  185.97ms │
│ Queries Faster                                              │         0 │
│ Queries Slower                                              │         0 │
│ Queries with No Change                                      │         8 │
│ Queries with Failure                                        │         0 │
└─────────────────────────────────────────────────────────────┴───────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and claude_groups-accumulator-indices-accounting
--------------------
Benchmark external_aggr.json
--------------------
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query        ┃                              HEAD ┃ claude_groups-accumulator-indices-accounting ┃    Change ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Q1(64.0 MB)  │    51.55 / 56.16 ±5.14 / 66.16 ms │               52.52 / 56.75 ±4.79 / 65.45 ms │ no change │
│ Q1(32.0 MB)  │    49.47 / 51.95 ±1.51 / 53.33 ms │               50.82 / 52.49 ±0.98 / 53.55 ms │ no change │
│ Q1(16.0 MB)  │    46.61 / 48.31 ±0.94 / 49.16 ms │               47.95 / 49.26 ±1.03 / 50.90 ms │ no change │
│ Q2(512.0 MB) │ 277.91 / 281.84 ±5.25 / 291.76 ms │            277.59 / 291.41 ±8.01 / 301.71 ms │ no change │
│ Q2(256.0 MB) │ 270.02 / 275.52 ±5.36 / 284.81 ms │           270.41 / 281.88 ±14.04 / 306.33 ms │ no change │
│ Q2(128.0 MB) │ 242.78 / 245.70 ±3.25 / 251.92 ms │            244.49 / 249.18 ±5.81 / 259.39 ms │ no change │
│ Q2(64.0 MB)  │ 242.33 / 245.49 ±3.95 / 253.09 ms │            242.95 / 244.26 ±1.50 / 247.12 ms │ no change │
│ Q2(32.0 MB)  │ 304.96 / 309.63 ±3.50 / 314.24 ms │            300.99 / 308.36 ±3.94 / 312.91 ms │ no change │
└──────────────┴───────────────────────────────────┴──────────────────────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                                           ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD)                                           │ 1514.58ms │
│ Total Time (claude_groups-accumulator-indices-accounting)   │ 1533.60ms │
│ Average Time (HEAD)                                         │  189.32ms │
│ Average Time (claude_groups-accumulator-indices-accounting) │  191.70ms │
│ Queries Faster                                              │         0 │
│ Queries Slower                                              │         0 │
│ Queries with No Change                                      │         8 │
│ Queries with Failure                                        │         0 │
└─────────────────────────────────────────────────────────────┴───────────┘

Memory Pool Peaks

Peak MemoryPool reservation per query — what DataFusion's accounting believes it reserved. Recorded only when the benchmark runs with DATAFUSION_RUNTIME_MEMORY_LIMIT set.

Base: da89c7c (merge-base) | Changed: claude/groups-accumulator-indices-accounting

external_aggr

Query Base Changed Change
1(64.0 MB) 38.5 MiB 36.8 MiB -4.5%
1(32.0 MB) 19.5 MiB 17.8 MiB -9.0%
1(16.0 MB) 11.4 MiB 11.4 MiB +0.1%
2(512.0 MB) 139.9 MiB 137.2 MiB -1.9%
2(256.0 MB) 97.9 MiB 97.9 MiB +0.0%
2(128.0 MB) 49.1 MiB 49.0 MiB -0.2%
2(64.0 MB) 29.2 MiB 29.2 MiB +0.0%
2(32.0 MB) 30.0 MiB 30.0 MiB +0.0%

Pool accounting vs. process RSS

Max pool peak is the largest reservation any single query in the run reached; peak RSS covers the whole invocation, including data loading and allocator retention, and the two high-water marks need not coincide in time. The gap is therefore an upper bound on what the pool did not account for, not a measurement of it.

Benchmark Side Max pool peak Peak RSS Gap RSS / pool
external_aggr base (da89c7c (merge-base)) 139.9 MiB 546.3 MiB 406.4 MiB 3.9×
external_aggr changed (claude/groups-accumulator-indices-accounting) 137.2 MiB 502.0 MiB 364.9 MiB 3.7×
Resource Usage

external_aggr — base (merge-base)

Metric Value
Wall time 510.1s
Peak memory 546.3 MiB
Avg memory 9.7 MiB
CPU user 22.4s
CPU sys 3.1s
Peak spill 0 B

external_aggr — branch

Metric Value
Wall time 525.1s
Peak memory 502.0 MiB
Avg memory 8.1 MiB
CPU user 25.7s
CPU sys 3.9s
Peak spill 0 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)

Comparing claude/groups-accumulator-indices-accounting (6b5b27b) to da89c7c (merge-base) diff

Run configuration
run benchmark clickbench_extended
env:
  DATAFUSION_RUNTIME_MEMORY_LIMIT: "4G"
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 claude_groups-accumulator-indices-accounting
--------------------
Benchmark clickbench_extended.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃        HEAD ┃ claude_groups-accumulator-indices-accounting ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │   797.53 ms │                                    776.47 ms │     no change │
│ QQuery 1  │   192.19 ms │                                    190.42 ms │     no change │
│ QQuery 2  │   462.45 ms │                                    454.26 ms │     no change │
│ QQuery 3  │   314.06 ms │                                    315.76 ms │     no change │
│ QQuery 4  │  1955.05 ms │                                   1979.67 ms │     no change │
│ QQuery 5  │ 18320.11 ms │                                  18403.94 ms │     no change │
│ QQuery 6  │     2.59 ms │                                      2.65 ms │     no change │
│ QQuery 7  │  6264.45 ms │                                   6766.97 ms │  1.08x slower │
│ QQuery 8  │   460.66 ms │                                    419.23 ms │ +1.10x faster │
│ QQuery 9  │  2640.14 ms │                                   2839.30 ms │  1.08x slower │
│ QQuery 10 │   637.60 ms │                                    631.07 ms │     no change │
│ QQuery 11 │  1904.26 ms │                                   1794.75 ms │ +1.06x faster │
│ QQuery 12 │   186.96 ms │                                    189.13 ms │     no change │
│ QQuery 13 │   548.52 ms │                                    542.13 ms │     no change │
└───────────┴─────────────┴──────────────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                                           ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                                           │ 34686.55ms │
│ Total Time (claude_groups-accumulator-indices-accounting)   │ 35305.75ms │
│ Average Time (HEAD)                                         │  2477.61ms │
│ Average Time (claude_groups-accumulator-indices-accounting) │  2521.84ms │
│ Queries Faster                                              │          2 │
│ Queries Slower                                              │          2 │
│ Queries with No Change                                      │         10 │
│ Queries with Failure                                        │          0 │
└─────────────────────────────────────────────────────────────┴────────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and claude_groups-accumulator-indices-accounting
--------------------
Benchmark clickbench_extended.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                      HEAD ┃ claude_groups-accumulator-indices-accounting ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │        797.53 / 856.67 ±60.60 / 970.36 ms │            776.47 / 787.25 ±8.46 / 797.34 ms │ +1.09x faster │
│ QQuery 1  │         192.19 / 193.23 ±0.88 / 194.61 ms │            190.42 / 194.17 ±6.79 / 207.74 ms │     no change │
│ QQuery 2  │         462.45 / 464.43 ±1.02 / 465.36 ms │            454.26 / 457.98 ±3.83 / 465.20 ms │     no change │
│ QQuery 3  │         314.06 / 317.99 ±2.11 / 320.27 ms │            315.76 / 321.46 ±3.41 / 326.15 ms │     no change │
│ QQuery 4  │     1955.05 / 2004.56 ±70.95 / 2142.25 ms │        1979.67 / 1997.79 ±18.17 / 2029.65 ms │     no change │
│ QQuery 5  │ 18320.11 / 18978.04 ±397.05 / 19445.19 ms │    18403.94 / 19212.88 ±602.73 / 20129.15 ms │     no change │
│ QQuery 6  │               2.59 / 2.81 ±0.26 / 3.32 ms │                  2.65 / 2.91 ±0.28 / 3.44 ms │     no change │
│ QQuery 7  │  6264.45 / 8139.53 ±2004.26 / 10820.59 ms │       6766.97 / 7013.61 ±202.28 / 7370.08 ms │ +1.16x faster │
│ QQuery 8  │         460.66 / 466.53 ±5.93 / 477.62 ms │           419.23 / 430.72 ±10.74 / 445.41 ms │ +1.08x faster │
│ QQuery 9  │    2640.14 / 2929.51 ±173.15 / 3109.68 ms │        2839.30 / 2922.24 ±99.87 / 3107.39 ms │     no change │
│ QQuery 10 │        637.60 / 655.73 ±18.85 / 682.59 ms │           631.07 / 655.71 ±20.04 / 689.13 ms │     no change │
│ QQuery 11 │     1904.26 / 1966.78 ±44.13 / 2031.80 ms │        1794.75 / 1906.79 ±73.99 / 2018.07 ms │     no change │
│ QQuery 12 │         186.96 / 194.01 ±5.87 / 204.81 ms │            189.13 / 192.58 ±2.22 / 195.51 ms │     no change │
│ QQuery 13 │        548.52 / 568.27 ±16.26 / 597.18 ms │           542.13 / 555.62 ±12.94 / 573.34 ms │     no change │
└───────────┴───────────────────────────────────────────┴──────────────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                                           ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                                           │ 37738.10ms │
│ Total Time (claude_groups-accumulator-indices-accounting)   │ 36651.70ms │
│ Average Time (HEAD)                                         │  2695.58ms │
│ Average Time (claude_groups-accumulator-indices-accounting) │  2617.98ms │
│ Queries Faster                                              │          3 │
│ Queries Slower                                              │          0 │
│ Queries with No Change                                      │         11 │
│ Queries with Failure                                        │          0 │
└─────────────────────────────────────────────────────────────┴────────────┘

Memory Pool Peaks

Peak MemoryPool reservation per query — what DataFusion's accounting believes it reserved. Recorded only when the benchmark runs with DATAFUSION_RUNTIME_MEMORY_LIMIT set.

Base: da89c7c (merge-base) | Changed: claude/groups-accumulator-indices-accounting

clickbench_extended

Query Base Changed Change
Query 0 830.8 MiB 814.8 MiB -1.9%
Query 1 3.4 MiB 3.4 MiB +0.0%
Query 2 98.1 MiB 102.1 MiB +4.0%
Query 3 11.7 MiB 11.7 MiB +0.0%
Query 4 1.4 GiB 1.4 GiB +0.2%
Query 5 1.5 GiB 1.5 GiB +1.1%
Query 6 104 B 104 B +0.0%
Query 7 1.2 GiB 1.2 GiB +0.0%
Query 8 37.0 MiB 37.2 MiB +0.5%
Query 9 2.2 GiB 2.1 GiB -3.4%
Query 10 1.7 MiB 2.1 MiB +25.1%
Query 11 2.1 GiB 2.1 GiB +0.5%
Query 12 1.1 MiB 1.0 MiB -12.0%
Query 13 520 B 520 B +0.0%

Pool accounting vs. process RSS

Max pool peak is the largest reservation any single query in the run reached; peak RSS covers the whole invocation, including data loading and allocator retention, and the two high-water marks need not coincide in time. The gap is therefore an upper bound on what the pool did not account for, not a measurement of it.

Benchmark Side Max pool peak Peak RSS Gap RSS / pool
clickbench_extended base (da89c7c (merge-base)) 2.2 GiB 9.5 GiB 7.4 GiB 4.4×
clickbench_extended changed (claude/groups-accumulator-indices-accounting) 2.1 GiB 8.8 GiB 6.7 GiB 4.2×
Resource Usage

clickbench_extended — base (merge-base)

Metric Value
Wall time 190.0s
Peak memory 9.5 GiB
Avg memory 4.1 GiB
CPU user 1898.8s
CPU sys 113.3s
Peak spill 0 B

clickbench_extended — branch

Metric Value
Wall time 185.0s
Peak memory 8.8 GiB
Avg memory 4.4 GiB
CPU user 1837.7s
CPU sys 117.9s
Peak spill 0 B

File an issue against this benchmark runner

A `Single` mode aggregate spills rather than emitting groups early, so
the scratch capacity the adapter now charges is observable as a spill: at
128 groups of 8192 rows the retained `indices` hold 4 MiB against a 1 MiB
limit, which the base commit runs straight past with `spill_count` 0.
@adriangb
adriangb marked this pull request as ready for review September 2, 2026 21:16
@adriangb
adriangb requested review from 2010YOUY01 and a balanced review from Copilot September 2, 2026 21:16
@adriangb

adriangb commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@2010YOUY01 mind reviewing this PR?

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.

🟢 Approval recommended

The accounting fix and regression coverage have no unresolved issues.

Pull request overview

Fixes memory accounting for retained scratch indices in GroupsAccumulatorAdapter, allowing memory limits and spilling to work correctly.

Changes:

  • Tracks and releases retained index-vector capacity.
  • Adds unit and end-to-end spill regression tests.
File summaries
File Description
datafusion/functions-aggregate-common/src/aggregate/groups_accumulator.rs Corrects scratch-memory accounting and adds unit tests.
datafusion/core/tests/memory_limit/mod.rs Verifies retained scratch memory triggers spilling.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

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

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.

4 participants