mrhhsg opened a new pull request, #69284:
URL: https://github.com/apache/doris/pull/69284

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Problem Summary:
   
   `percentile_approx` and `quantile_union` keep one `TDigest` per GROUP BY 
group. The
   `TDigest(compression, unmerged_size, merged_size)` constructor eagerly 
reserved
   `2 * compression` processed centroids and `8 * compression + 1` unprocessed 
centroids before
   any value was stored. At the default `compression = 10000` this costs 800008 
bytes per group
   (160000 B + 640008 B), independent of how many rows the group actually holds.
   
   Both allocations exceed the ASAN primary allocator's 128 KiB size-class 
limit, so each digest
   occupied two secondary-allocator chunks. With roughly 524288 live groups the 
process exhausted
   the secondary allocator's chunk table (`kMaxNumChunks = 1 << 20`) and 
aborted in
   `sanitizer_allocator_secondary.h:42`. Release builds map about 480 GB of 
virtual address space
   for 600K singleton groups in the same scenario.
   
   Fix:
   
   - Let both vectors grow on demand in the constructor. `_max_processed` and 
`_max_unprocessed`
     are still initialized exactly as before: they are compression thresholds 
used by
     `is_dirty()`, the buffered `add()` path, and serialization, not capacity 
caches.
   - Remove the exact-size `reserve(total)` from `_merge_unprocessed`. Once the 
constructor no
     longer preallocates, `reserve(total)` would reallocate and copy the whole 
buffer on every
     merge of a small digest, degrading many sequential merges to O(n^2) 
copies. `insert()` grows
     geometrically instead, keeping amortized O(1).
   
   The compression thresholds, the t-digest algorithm, the numeric results, and 
the serialized
   format are unchanged.
   
   Tests updated/added:
   
   - New unit test: a default-constructed digest has zero buffer capacity, 
allocates less than
     4 KiB in total, keeps the historical thresholds (20000 / 80000), and still 
returns the right
     quantile after a single value.
   - New unit test: 1000 singleton groups allocate memory proportional to their 
data
     (< 1 KiB per group) and each returns the correct median.
   - Updated an existing accumulator test that previously asserted the 80001 
preallocation; it
     now asserts that the accumulator retains spare write-buffer capacity 
without encoding the
     removed preallocation.
   
   ### Release note
   
   Fix backend aborts for `percentile_approx` / `quantile_union` queries with a 
very high number
   of GROUP BY groups by no longer preallocating compression-sized buffers per 
group.
   
   ### Check List (For Author)
   
   - Test: Unit Test
       - BE unit tests under ASAN: 41 tests from 5 suites passed, covering 
`TDigestTest`
         (including the two new capacity/memory tests), `QuantileStateTest`,
         `AggregateFunctionPercentileApproxArrayTest`, 
`AggregateFunctionQuantileStateTest`,
         and `AggregateFunctionQuantileStateRangeTest`. Command:
         `./run-be-ut.sh --run 
--filter='TDigestTest.*:QuantileStateTest.*:AggregateFunctionPercentileApproxArrayTest.*:AggregateFunctionQuantileStateTest.*:*AggregateFunctionQuantileStateRangeTest.*'
 -j 64`
       - A standalone ASAN program holding 600000 live `TDigest` instances now 
runs to
         completion; the same program aborted at about 524288 digests before 
the fix.
       - A negative-control build against the old header confirms the new 
assertions fail on the
         unfixed code (capacities 20000 / 80001 and 800008 bytes per digest; 
1000 singleton
         groups allocate 800008000 bytes).
       - `clang-format` (v16) passes on the changed files, the repository-wide 
format check
         passes, and the build-hygiene check passes.
       - `clang-tidy` could not run on this machine: its toolchain reports
         `'stddef.h' file not found` for the changed files, unrelated to this 
change.
       - No regression test was added: reproducing the abort requires more than 
~524288 live
         digests, which no regression cluster can hold, and release builds 
neither abort nor
         return an error row. The new unit tests assert the exact capacity and 
allocation
         behavior at the layer where the fix lives.
   - Behavior changed: No
   - Does this need documentation: No


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to