[improvement](be) Decouple build index memory limit from schema change and make it dynamic#62398
Open
zhiqiang-hhhh wants to merge 4 commits intoapache:masterfrom
Open
Conversation
…e and make it dynamic
### What problem does this PR solve?
Issue Number: close #xxx
Problem Summary:
Previously, build index tasks reused the schema change memory limit
(`schema_change_mem_limit_frac`), which was shared with ALTER TABLE
operations and divided statically by `alter_tablet_worker_count` (a
wrong divisor — should have been `alter_index_worker_count`). This
caused two problems:
1. Single build index tasks were unnecessarily constrained — they could
not leverage available memory even when the system was idle.
2. There was no awareness of real-time memory pressure. Under heavy
system load, build index tasks would still claim the same amount of
memory, increasing OOM risk.
This PR introduces an independent, dynamic memory limit strategy for
build index tasks with the following behavior:
- Each task gets up to `soft_mem_limit * build_index_mem_limit_frac`
(default 0.6) — no static division by worker count.
- The limit is capped by actual remaining memory
(`soft_mem_limit - process_memory_usage`), so concurrent tasks
naturally get less when the system is under pressure.
- Two-tier watermark throttling further reduces the budget:
- Low watermark (75%): limit halved.
- High watermark (85%): limit reduced to `min_limit` (effectively
rejecting the task if it needs more).
- A floor of `build_index_min_memory_per_task_bytes` (default 2GB)
prevents starvation.
- All four config parameters are mutable (`DEFINE_m*`), adjustable at
runtime without BE restart.
### Release note
Added independent mutable configuration for build index memory limits:
`build_index_mem_limit_frac`, `build_index_min_memory_per_task_bytes`,
`build_index_memory_high_watermark_pct`,
`build_index_memory_low_watermark_pct`. Build index tasks now use
dynamic memory limits based on real-time system memory pressure instead
of sharing the static schema change memory limit.
### Check List (For Author)
- Test: Unit Test
- Behavior changed: Yes — build index tasks now have independent memory
limits and are sensitive to system memory pressure. Default budget
is `soft_mem_limit * 0.6` (previously `soft_mem_limit * 0.6 /
alter_tablet_worker_count`), so single-task scenarios get
significantly more memory.
- Does this need documentation: No
🐘 Generated with Crush
Assisted-by: Claude Opus 4.6 via Crush <crush@charm.land>
Contributor
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
### What problem does this PR solve? Issue Number: close #xxx Related PR: #xxx Problem Summary: Fix code formatting issues detected by clang-format 16 in storage_engine.cpp and build_index_memory_limit_test.cpp ### Release note None ### Check List (For Author) - Test: No need to test (formatting-only changes, no logic change) - Behavior changed: No - Does this need documentation: No
Contributor
Author
|
run buildall |
Contributor
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
Contributor
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
Contributor
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
1 similar comment
Contributor
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
### What problem does this PR solve? Problem Summary: 1. SIGSEGV crash in alter_inverted_index_callback: _mem_tracker was created in execute() but SCOPED_ATTACH_TASK accessed it before execute() was called, causing null pointer dereference in memory_context.h:82. 2. When build_index_mem_limit_frac=0, the function returned 0 instead of min_limit, bypassing the floor guarantee. 3. running_build_index_tasks() was public but only used in tests. 4. No logging for actual memory limit assigned to build index tasks. Fix: - Move _mem_tracker creation and notify_build_index_task_begin to constructor, notify_build_index_task_end to destructor (RAII) for both EngineIndexChangeTask and EngineCloudIndexChangeTask. - Add std::max(limit, min_limit) as final floor guarantee in memory_limitation_bytes_for_build_index(). - Move running_build_index_tasks() to private with FRIEND_TEST. - Add INFO log on task creation with tablet_id and mem_limit. - Add 4 boundary-value tests: zero frac, frac>1, inverted watermarks, zero min_bytes. ### Release note None ### Check List (For Author) - Test: Unit Test (BuildIndexMemoryLimitTest, 11 tests all passed) - Behavior changed: No - Does this need documentation: No 🐮 Generated with Crush Assisted-by: Claude Opus 4.6 via Crush <crush@charm.land>
Contributor
Author
|
run buildall |
Contributor
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
Contributor
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
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.
Summary
Build index tasks previously reused the schema change memory limit (
schema_change_mem_limit_frac), which was statically divided byalter_tablet_worker_count. This caused two problems:alter_index_worker_count).This PR introduces an independent, dynamic memory limit strategy for build index tasks, optimized for the common case (single task, give it maximum memory) while protecting against OOM during rare concurrent execution.
New Strategy
Each build index task gets up to
soft_mem_limit × build_index_mem_limit_frac(default 60%), no division by task count. The actual limit is then constrained by two mechanisms:1. Remaining Memory Cap
When the first task is already consuming memory, subsequent tasks naturally see less remaining memory. If the remaining memory is below
min_limit(default 2GB), the task will likely fail due to the mem tracker — this is the intended behavior to prevent OOM.2. Watermark-based Throttling
min_limitonlyConfiguration (all mutable at runtime)
build_index_mem_limit_fracbuild_index_min_memory_per_task_bytesbuild_index_memory_high_watermark_pctbuild_index_memory_low_watermark_pctMem Tracker & Task Counting Lifecycle
The
MemTrackerLimiterand task counting (notify_build_index_task_begin/end) are managed in the constructor/destructor ofEngineIndexChangeTask/EngineCloudIndexChangeTask. This is necessary becausealter_inverted_index_callbackcallsSCOPED_ATTACH_TASK(engine_task.mem_tracker())beforeexecute(), so_mem_trackermust be initialized by the time the task object is constructed. The task counting must also happen in the constructor (before_mem_trackercreation) so thatmemory_limitation_bytes_for_build_index()sees the correct concurrent task count.Key Code Changes
config.h/cpp— 4 new mutable configs (DECLARE_m*/DEFINE_m*)storage_engine.h/cpp—memory_limitation_bytes_for_build_index()with remaining-memory cap + watermark throttling;notify_build_index_task_{begin,end}()for task counting;_running_build_index_tasksatomic counterengine_index_change_task.cpp— Switched to new dynamic memory limit API; task counting and mem tracker in constructor/destructorengine_cloud_index_change_task.cpp— Same changes for cloud pathbuild_index_memory_limit_test.cpp— 7 unit tests covering: task counting, full budget, remaining memory cap, min floor, high/low watermark throttling, config mutabilityTest Plan
BuildIndexMemoryLimitTest.*(7 tests, all passed)