Repository navigation
Conversation
Use hashbrown's allocation_size() to include retained buckets and control bytes. Count embedded accumulator fields once, and include the separately boxed dictionary accumulator's wrapper. Add regression tests for retained capacity, inclusive accumulator sizes, and memory-limit enforcement with floating-point distinct aggregates. Validation: formatting, all-target/all-feature Clippy, all 21 rust_lint steps, and 545 SQLLogicTest files pass. Paired allocation and SQL probes verify retained sizes, results, quota failures, and reservation cleanup. The full workspace extended run reports 13344 passed, 1 failed, 8 ignored. The sort_query_fuzzer_runner failure reproduces deterministically on unmodified upstream 49c67c2 and this patch with an ORDER BY-only query and an unbounded memory pool. It remains a separate upstream issue. Refs: apache#26937
|
Quick update: I'm testing a further refinement to improve memory accounting accuracy for small primitive The candidate replaces Preliminary Windows validation is promising:
I'm proceeding with Linux allocation and performance validation before incorporating this refinement into the PR. I'll update the implementation and testing summary once the results are confirmed. |
Use datafusion_common::HashSet and allocation_size() while preserving the explicit hasher. Cover capacity boundaries, wide decimal keys, nulls, overlapping merges and retained capacity, and add insertion/merge benchmarks. Validation: cargo fmt --all, all-target/all-feature Clippy with -D warnings, 67 aggregate-common tests and aggregate.slt pass. Independent Windows heap probes have zero error across 41 scenarios and five types. The extended workspace attempt is not fully green: 1974 passed and one Q15 unparser multi-statement failure, before accumulator construction, with parser/test/fixture unchanged from the PR base. Later workspace binaries were not run. Refs: apache#26937
|
Update: Linux validation and performance investigation The hashbrown-based memory accounting change is now pushed in However, controlled real-SQL benchmarks revealed a reproducible regression in nullable The investigation narrowed the regression to insert-path code generation and inlining. A separate, local hashbrown prototype changes one attribute on On Rocky Linux, compared with the matching unmodified hashbrown baseline:
The major Int32 merge regression observed with earlier experimental approaches did not reproduce. The main SQL improvements were also confirmed in independent interleaved runs. I plan to validate its broader performance and compilation-cost impact before seeking upstream hashbrown review. |
|
Thank you for the contribution. The change may well be correct, but I am closing this PR under our AI policy. Maintainer review time is the scarcest resource in this project. This account has recently opened many AI-generated PRs across many repositories. That suggests the changes aren't coming from someone who uses DataFusion, and that no human will be around to discuss review feedback and maintain the code. Reviewing PRs like this costs us more time than it saves. If you do use DataFusion and this fix matters to you, please pick the one change you care most about. Then open a focused PR with a short description in your own words, one you have reviewed and understand, and we'd be happy to help with review. |
|
@alamb First, I have never submitted AI-generated PRs to external open-source projects. Before this DataFusion PR, the only external projects I contributed PRs to were WinUI 3 and Electrobun, and I wrote both myself. All other PRs are for projects I own or develop with friends. I don't understand why you claimed that I have submitted large numbers of AI-generated PRs across different projects. I would like to know what evidence you based this claim on. Second, this PR is still a Draft. I didn't request a review. I am still working on the code, test data, and report, and investigating the performance regression. I don't understand how this could be considered an additional review burden when I haven't even asked anyone to review it. Finally, I don't understand why you assume I don't use DataFusion, won't discuss review feedback, or won't maintain my contribution. I have been actively working on this PR, posting progress updates, running tests across different platforms, and exploring possible solutions. I haven't even finished working on this PR yet, so I find it unreasonable to assume that I would abandon it or refuse to maintain it. I'm not asking you to reopen this PR. I simply disagree with these unfair accusations and would like an explanation for them. |
Which issue does this PR close?
Closes #26937. Related to #23393 and #25650; discovered while investigating #20942.
Rationale
DISTINCT aggregation can retain significantly more HashSet memory than it reports to DataFusion's MemoryPool. For example, an 8,192-row Float64 batch with 128 distinct values retains 147,472 bytes of heap while the original estimator reports 2,344 bytes, allowing queries to exceed their expected memory reservation.
Some nested accumulators also double-count embedded objects. Primitive COUNT(DISTINCT) additionally had a small residual error from capacity-based estimation.
Changes
allocation_size()to account forGenericDistinctBuffer's retained HashSet heap and count the accumulator object once.PrimitiveDistinctCountAccumulatorto the existingdatafusion_common::HashSet(hashbrown), keeping its explicitRandomStatehasher, and account for allocations directly.SQL results and public APIs are unchanged.
Validation
Memory accounting
Independent Windows/MSVC and Rocky Linux allocator measurements each covered 41 scenarios × 5 accumulator types × 3 revisions × 50 repetitions = 30,750 observations. All 10,250 current-revision observations per platform had zero requested-retained-heap estimation error; the 615 scenario/type/revision summaries matched across platforms. Tests include small allocated tables, reservation boundaries, chunked updates, retained capacity after clear and cleanup on drop.
Example: 8,192 rows / 128 NDV (retained heap bytes, excluding the inline accumulator):
The
size()checks do not allocate; tested drop and low-memory SQL paths release their reservations.Correctness and repository checks
aggregate.sltand benchmark correctness checks passed.test_tpch_unparser_roundtripfailure involving Q15 multi-statement planning (1,483 other core integration tests passed); the full workspace run remains incomplete.Performance and current status
The pushed PR head
46af5e0a7resolves the measured memory-accounting errors, but stock hashbrown 0.17.1 shows a repeatable regression in real nullable Int64COUNT(DISTINCT)SQL on Rocky Linux (about 5.76 → 6.36 ms versus the previous std-HashSet revision). This PR therefore remains Draft.An independently tested hashbrown-side candidate changes
HashMap::insertfrominlinetoinline(always)under its existinginline-morefeature. Against the matching unmodified hashbrown build, it improves:Independent paired runs confirmed the main SQL gains; the earlier large Int32 merge regression of another experimental approach did not recur. The inline candidate also retained zero estimation error across 20,500 additional allocator observations.
This dependency-side optimization is not part of the pushed DataFusion PR or a released hashbrown version. Wider consumer/compilation-cost validation and upstream hashbrown review are next. See the latest investigation update.
User-facing impact
Accurate retained-state accounting may trigger
ResourcesExhaustedearlier under tight memory budgets, while corrected double-counting avoids unnecessary overcharging.