Skip to content

Reduce memory consumption in aggregator#109224

Merged
scanhex12 merged 2 commits into
ClickHouse:masterfrom
scanhex12:memory_consumption
Jul 3, 2026
Merged

Reduce memory consumption in aggregator#109224
scanhex12 merged 2 commits into
ClickHouse:masterfrom
scanhex12:memory_consumption

Conversation

@scanhex12

@scanhex12 scanhex12 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Changelog category (leave one):

  • Improvement

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

Reduce memory consumption in aggregator

Version info

  • Merged into: 26.7.1.473 (included in 26.7 and later)
  • Backported to: 26.6.2.27

@clickhouse-gh

clickhouse-gh Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Workflow [PR], commit [e4b7f58]

Summary:

job_name test_name status info comment
Stress test (amd_asan_ubsan) FAIL
Hung check failed, possible deadlock found FAIL cidb, issue
Stress test (arm_tsan) FAIL
Logical error: Block structure mismatch in A stream: different number of columns: (STID: 0993-308a) FAIL cidb, issue

AI Review

Summary

This PR tries to reduce memory usage while spilling aggregated data to temporary files by moving the converted columns out of AggregatedChunk before writing them. The ownership shuffle is not enough on its own, though: the spilled columns still stay alive in the local Block until the same point in the loop, so the claimed memory reduction is not established by the current implementation.

Findings

⚠️ Majors

  • [src/Interpreters/Aggregator.cpp:1945] The PR promises lower memory usage during external aggregation, but detachColumns() here only transfers ownership from agg_chunk.chunk to block. Block::setColumns copies the same ColumnPtrs into block, NativeWriter::write consumes that Block synchronously, and block is still kept alive through update_max_sizes(block) below. That means the ColumnAggregateFunction objects and their arenas are released at the same point as before, so the spill path does not actually free memory earlier.
    Suggested fix: either destroy/clear block immediately after out->write(block) and compute the size stats before that, or use another approach that demonstrably shortens the lifetime of the spilled columns.
Tests
  • ⚠️ This is an Improvement PR, but there is no focused before/after measurement showing reduced peak memory on the external aggregation spill path. A small repro that forces spilling and reports peak memory before and after the fix would close the gap.
Final Verdict

Status: ⚠️ Request changes

Minimum required actions:

  1. Make the spill path actually release the written aggregate columns earlier, or explain with evidence why the current ownership change already reduces peak memory.
  2. Add a focused before/after measurement for the external aggregation spill case.

@clickhouse-gh clickhouse-gh Bot added the pr-improvement Pull request with some product improvements label Jul 2, 2026
@grantholly-clickhouse

Copy link
Copy Markdown
Contributor

IIUC, we are now going to move the columns to the block so that they are not held onto until the very end by the source chunk.

@grantholly-clickhouse grantholly-clickhouse 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.

LGTM

block.setColumns(agg_chunk.chunk.getColumns());
block.info.bucket_num = agg_chunk.bucket_num;
block.info.is_overflows = agg_chunk.is_overflows;
block.setColumns(agg_chunk.chunk.detachColumns());

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.

detachColumns() only moves ownership from agg_chunk.chunk into the local block; it does not shorten the lifetime of the spilled aggregate columns themselves. Block::setColumns still copies those ColumnPtrs into block, NativeWriter::write is synchronous, and block stays alive through update_max_sizes(block) below, so the ColumnAggregateFunction objects and their arenas are released at the same point as before. As written, this does not actually deliver the PR's promised memory reduction on the spill path. Please either drop block immediately after the write (or compute the stats before the write and clear it afterward) and attach a before/after measurement, or explain what other lifetime change is supposed to lower peak memory here.

@clickhouse-gh

clickhouse-gh Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

LLVM Coverage Report

Metric Baseline Current Δ
Lines 85.50% 85.50% +0.00%
Functions 92.60% 92.60% +0.00%
Branches 77.70% 77.70% +0.00%

Changed lines: Changed C/C++ lines covered: 13/13 (100.00%) · Uncovered code

Full report · Diff report

@scanhex12
scanhex12 added this pull request to the merge queue Jul 3, 2026
Merged via the queue into ClickHouse:master with commit 882ae8e Jul 3, 2026
171 of 175 checks passed
@scanhex12
scanhex12 deleted the memory_consumption branch July 3, 2026 10:06
@robot-clickhouse-ci-2 robot-clickhouse-ci-2 added the pr-synced-to-cloud The PR is synced to the cloud repo label Jul 3, 2026
@KochetovNicolai KochetovNicolai added the pr-must-backport Pull request should be backported intentionally. Use this label with great care! label Jul 3, 2026
@robot-clickhouse-ci-2 robot-clickhouse-ci-2 added the pr-must-backport-synced The `*-must-backport` labels are synced into the cloud Sync PR label Jul 3, 2026
clickhouse-gh Bot added a commit that referenced this pull request Jul 3, 2026
Backport #109224 to 26.6: Reduce memory consumption in aggregator
@alexey-milovidov alexey-milovidov removed the pr-must-backport Pull request should be backported intentionally. Use this label with great care! label Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-improvement Pull request with some product improvements pr-must-backport-synced The `*-must-backport` labels are synced into the cloud Sync PR pr-synced-to-cloud The PR is synced to the cloud repo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants