Repository navigation
perf: KLL and HLL aggregate states in DuckDB's arena, so they count toward memory_limit and spill - #27
Merged
Conversation
… spill Sketch states lived on the heap with a destructor, so DuckDB neither counted them toward memory_limit nor spilled them: a 2M-group KLL aggregate used 39 GB under a 1 GB limit. KLL (every item type but VARCHAR) and HLL states now live in the aggregate arena (DSAllocator's new arena mode, allocating from the arena of the running callback), have no destructor, and export and import their sketches as BLOBs, which DuckDB 2.0 uses to spill aggregate states. DuckDB creates one state per input row when grouping reduces little, so KLL states keep their first 32 items in a growing buffer and build a sketch only when more arrive; small exact input sketches are buffered too, and buffered states export as raw items. The same KLL query now runs in 0.8 GB under a 1 GB limit, 3.7x faster. The vcpkg overlay carries three library fixes sent upstream: hll-union-allocator (apache/datasketches-cpp#556), ebpps-merge-qualified-swap (#557, which removes our copy-then-merge workaround) and kll-lazy-items (#558). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DuckDB 2.0 can spill aggregate states to disk, but only for states that live in the aggregate arena, have no destructor, and register export and import callbacks. Our states were heap objects with destructors. So DuckDB couldn't see their memory, and
memory_limitdidn't apply to them.datasketch_kll(200, v), 1 GB limitdatasketch_hll(12, v), 4 GB limitapprox_quantile(built-in)What changed
DSAllocatorarena mode: it allocates from the arena of the aggregate callback that's currently running (DSArenaScope) and never frees. Each sketch grows only in an arena that the current thread is allowed to use. When states combine, the source is copied into the target's arena rather than taken over.std::stringitems allocate their own memory.MaybeSkipLookups). So KLL states keep their first 32 items in an array that grows as needed, and build a sketch only when more arrive; results are unchanged. Small exact input sketches are buffered the same way, and buffered states export as raw items, so spilled states don't come back full size.Library patches (in the vcpkg overlay, port-version 3)
hll-union-allocator.patch: fix: hll_union kept memory of input sketches' allocators apache/datasketches-cpp#556. Without it, HLL unions kept heap copies of their inputs.ebpps-merge-qualified-swap.patch: fix: ebpps_sketch::merge(const&) called an unqualified swap apache/datasketches-cpp#557. This lets us drop the EBPPS copy-then-merge workaround.kll-lazy-items.patch: perf: kll_sketch allocates its items on first use apache/datasketches-cpp#558.Tests
New
test/sql/datasketch_spill.test, run under a 128MB limit with 4 threads:EXPORT_STATEround tripsAll tests pass on EC2: 32 test files, 1953 assertions.
Still to do (next PRs)
🤖 Generated with Claude Code