github-actions[bot] commented on code in PR #68712:
URL: https://github.com/apache/doris/pull/68712#discussion_r4175757746


##########
be/src/exec/scan/scanner_context.cpp:
##########
@@ -166,14 +164,17 @@ int ScannerContext::_available_pickup_scanner_count() {
     P.adjust_scanners_last_timestamp = now;
     auto old_scanners = P.expected_scanners;
 
-    scanners = std::max(min_scanners, scanners);
-    scanners = std::min(max_scanners, scanners);
+    // The memory limiter is what adapts: its ceiling shrinks when blocks are 
estimated larger or
+    // the query's scan budget is shared by more scan nodes, and grows back 
when they are not. Take
+    // the whole ceiling. Clamping the previous value into [minimum, ceiling] 
instead never raises
+    // it above the minimum, since expected_scanners starts at zero, so every 
scan would keep a
+    // single scanner however much memory there is. The ceiling still wins 
over the minimum, and a
+    // scheduler without slack still holds the Context at its minimum in 
_get_margin() and
+    // can_admit_scan_task().

Review Comment:
   [P1] Keep this behind #68710's BE JVM thread-exit fix. For a one-instance 
fluss or paimon scan, assigning the full ceiling can admit all 16 JNI readers 
because the limiter budgets native block memory, while BE's JVM has a separate 
default 2 GB heap. The PR descriptions document a heavy 16-bucket read 
exhausting that heap and a library worker calling `System.exit`, which takes 
down BE. #68710 is still open, so merging this head first makes that process 
failure reachable by default.



##########
be/src/exec/scan/scanner_context.cpp:
##########
@@ -166,14 +164,17 @@ int ScannerContext::_available_pickup_scanner_count() {
     P.adjust_scanners_last_timestamp = now;
     auto old_scanners = P.expected_scanners;
 
-    scanners = std::max(min_scanners, scanners);
-    scanners = std::min(max_scanners, scanners);
+    // The memory limiter is what adapts: its ceiling shrinks when blocks are 
estimated larger or
+    // the query's scan budget is shared by more scan nodes, and grows back 
when they are not. Take
+    // the whole ceiling. Clamping the previous value into [minimum, ceiling] 
instead never raises
+    // it above the minimum, since expected_scanners starts at zero, so every 
scan would keep a
+    // single scanner however much memory there is. The ceiling still wins 
over the minimum, and a
+    // scheduler without slack still holds the Context at its minimum in 
_get_margin() and
+    // can_admit_scan_task().

Review Comment:
   [P2] Preserve a zero per-instance allocation when TaskExecutor replaces a 
completed scanner. This assignment can grow instance 1 of a two-instance scan 
to two scanners; after larger block samples, `available_scanner_count(1)` can 
fall to zero. Consuming one non-EOS result still leaves another task occupied, 
but `_get_margin()` requests one and `_pull_next_scan_task()` maps 
`expected_scanners == 0` to `_max_scan_concurrency`, so it immediately replaces 
the consumed scanner instead of draining to the one progress task. Keep zero as 
the ceiling while any task remains occupied, and test that shrink transition.



##########
be/src/exec/scan/scanner_context.cpp:
##########
@@ -166,14 +164,17 @@ int ScannerContext::_available_pickup_scanner_count() {
     P.adjust_scanners_last_timestamp = now;
     auto old_scanners = P.expected_scanners;
 
-    scanners = std::max(min_scanners, scanners);
-    scanners = std::min(max_scanners, scanners);
+    // The memory limiter is what adapts: its ceiling shrinks when blocks are 
estimated larger or
+    // the query's scan budget is shared by more scan nodes, and grows back 
when they are not. Take
+    // the whole ceiling. Clamping the previous value into [minimum, ceiling] 
instead never raises
+    // it above the minimum, since expected_scanners starts at zero, so every 
scan would keep a
+    // single scanner however much memory there is. The ceiling still wins 
over the minimum, and a
+    // scheduler without slack still holds the Context at its minimum in 
_get_margin() and
+    // can_admit_scan_task().

Review Comment:
   [P2] Count completed tasks in the TaskExecutor low-memory cap. After this 
change admits 16 file scanners, a query can enter low-memory mode with 16 
completed blocks queued. Consuming one leaves 15 completed; `_get_margin()` 
caps with `4 - _in_flight_tasks_num` (4), omitting those blocks, and its 
adaptive margin admits one replacement. The queue can remain at 16 under memory 
pressure instead of draining toward four. Use completed-plus-in-flight 
accounting as `can_admit_scan_task()` does, and cover this transition.



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