Yukang-Lian opened a new pull request, #65963:
URL: https://github.com/apache/doris/pull/65963

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: None
   
   Problem Summary:
   
   #### Problem
   
   Vertical compaction lazily opens one segment per input rowset for valid
   NONOVERLAPPING rowsets. In the value-column merge path, however, a segment
   context was retained after its last row source had already been consumed.
   Its segment reader and decoded Blocks were not released until the whole value
   group was destroyed.
   
   As a result, the number of retained contexts grew with the total input 
segment
   count instead of staying near the merge way/input rowset count. This caused
   vertical compaction peak memory to grow linearly with segment count even when
   the rowsets were non-overlapping.
   
   This was delayed resource release during compaction, not a permanent leak:
   the contexts were eventually released when the value group ended.
   
   #### Root cause
   
   `RowSourcesBuffer` recorded which segment produced each output row, but did
   not expose when a source had been consumed for the last time. The value paths
   therefore had no lifecycle boundary at which they could safely release an
   exhausted `VerticalMergeIteratorContext`.
   
   #### Fix
   
   - Record each source's last global row-source position. The position remains
     correct when `RowSourcesBuffer` spills and is reset by `seek_to_begin()`
     between value groups.
   - After returning the last row or batch for a source, release that context's
     segment iterator and context-owned Blocks. Returned `IteratorRowRef` and
     `RowBatch` objects retain their own `shared_ptr<Block>`, so their data 
remains
     valid.
   - Cover AGG `next_row()`, UNIQUE fallback `unique_key_next_row()`, and UNIQUE
     sparse-batch `unique_key_next_batch()`.
   - Add current and peak Bvars for active vertical-compaction segment contexts:
     `vertical_compaction_active_segment_contexts` and
     `vertical_compaction_active_segment_contexts_peak`.
   - Keep the key-group heap merge, DUP batch path, compaction selection, batch
     sizing, and MemTracker accounting unchanged.
   
   #### Verification
   
   The before/after memory test uses identical deterministic input: 10
   NONOVERLAPPING input rowsets, 32,000 rows, an 8 KiB VARCHAR payload per row,
   and compaction batch size 32.
   
   | Input | Context peak before | Context peak after | Memory peak before | 
Memory peak after |
   |---|---:|---:|---:|---:|
   | 100 segments | 100 | 10 | 51.89 MiB | 6.1145 MiB |
   | 500 segments | 500 | 10 | 255.14 MiB | 6.1047 MiB |
   
   Adding 400 segments increased the pre-fix peak by about 203 MiB. After the
   fix, the two memory peaks differ by only 10,250 bytes. Repeated runs produced
   the same context and memory peaks.
   
   Additional lifecycle coverage verifies:
   
   - UNIQUE fallback: 3 rowsets x 4 segments, context peak reduced from 12 to 3.
   - UNIQUE sparse batch: context peak is 3, with sparse optimization confirmed
     enabled.
   - AGG row path: 2 rowsets x 2 segments, context peak is 2.
   - Current context count returns to zero after every compaction.
   - Output keys, 8 KiB payloads, delete signs, and row counters are unchanged.
   - Spill and `seek_to_begin()` preserve global source-position tracking.
   
   Focused ASAN BE unit tests passed:
   
   ```text
   6/6:
     TestRowSourcesBuffer
     TestRowSourcesBufferSpillThreshold
     TestUniqueKeyVerticalMerge
     TestUniqueKeyNonOverlappingSegmentContextRetention
     TestUniqueKeySegmentContextMemoryAmplification
     TestUniqueKeyVerticalMergeWithNullableSparseColumn
   
   3/3:
     TestAggKeyVerticalMerge
     RowBatchSharedPtrLifetime
     RowBatchVector
   
   Review follow-up 2/2:
     TestUniqueKeyNonOverlappingSegmentContextRetention
     TestAggKeyVerticalMerge
   ```
   
   `build-support/check-format.sh` and `git diff --check` passed. The changed
   production code also compiled with `-Wall -Wextra -Werror` in the ASAN unit
   test build. Production-file clang-tidy is currently blocked by the existing
   unmatched `NOLINTEND` at `be/src/core/types.h:576` on master, unrelated to
   this change.
   
   ### Release note
   
   Reduce vertical compaction peak memory by releasing exhausted segment readers
   and decoded Blocks during value-column merging.
   
   ### Check List (For Author)
   
   - Test
       - [ ] Regression test
       - [x] Unit Test
       - [x] Manual test (detailed verification is included above)
       - [ ] No need to test or manual test. Explain why:
           - [ ] This is a refactor/code format and no logic has been changed.
           - [ ] Previous test can cover this change.
           - [ ] No code files have been changed.
           - [ ] Other reason
   
   - Behavior changed:
       - [ ] No.
       - [x] Yes. Exhausted value-path segment contexts are released immediately
         after their final row source is handed to the caller.
   
   - Does this need documentation?
       - [x] No.
       - [ ] Yes.
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   - [ ] Confirm document
   - [ ] Add branch pick label
   


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