This is an automated email from the ASF dual-hosted git repository.

mrhhsg pushed a commit to branch opt_perf_4.1
in repository https://gitbox.apache.org/repos/asf/doris.git

commit b61927b78c8f327bcf02fb80fb4e94fc2123885e
Author: Hu Shenggang <[email protected]>
AuthorDate: Tue Jul 14 15:44:05 2026 +0800

    Revert "[opt](scan) Boost scanner concurrency under starvation"
    
    This reverts commit 7261a1e48beb0940bc5c9a016f02bda65fbfe895.
---
 be/src/exec/scan/scanner_context.cpp               | 28 ++++------------------
 be/src/exec/scan/scanner_context.h                 |  3 +--
 be/src/exec/scan/scanner_scheduler.cpp             |  2 +-
 be/test/exec/scan/scanner_context_test.cpp         | 25 -------------------
 .../java/org/apache/doris/qe/SessionVariable.java  |  4 ++--
 5 files changed, 9 insertions(+), 53 deletions(-)

diff --git a/be/src/exec/scan/scanner_context.cpp 
b/be/src/exec/scan/scanner_context.cpp
index 3371af5bf8e..f7376fd2946 100644
--- a/be/src/exec/scan/scanner_context.cpp
+++ b/be/src/exec/scan/scanner_context.cpp
@@ -166,7 +166,6 @@ Status ScannerContext::init() {
             }
         }
     }
-    _min_scan_concurrency = std::min(_min_scan_concurrency, 
_max_scan_concurrency);
 
     COUNTER_SET(_local_state->_max_scan_concurrency, 
(int64_t)_max_scan_concurrency);
     COUNTER_SET(_local_state->_min_scan_concurrency, 
(int64_t)_min_scan_concurrency);
@@ -258,7 +257,6 @@ void 
ScannerContext::push_back_scan_task(std::shared_ptr<ScanTask> scan_task) {
     }
     _tasks_queue.push_back(scan_task);
     _num_scheduled_scanners--;
-    _scan_starving = false;
 
     _dependency->set_ready();
 }
@@ -318,13 +316,9 @@ Status ScannerContext::get_block_from_queue(RuntimeState* 
state, Block* block, b
             if (scan_task->is_eos()) {
                 // 1. if eos, record a finished scanner.
                 _num_finished_scanners++;
-                _scan_starving = _tasks_queue.empty() &&
-                                 _num_finished_scanners < 
cast_set<int32_t>(_all_scanners.size()) &&
-                                 (_num_scheduled_scanners > 0 || 
!_pending_scanners.empty());
                 RETURN_IF_ERROR(
                         
_scanner_scheduler->schedule_scan_task(shared_from_this(), nullptr, l));
             } else {
-                _scan_starving = _tasks_queue.empty();
                 RETURN_IF_ERROR(
                         
_scanner_scheduler->schedule_scan_task(shared_from_this(), scan_task, l));
             }
@@ -339,12 +333,7 @@ Status ScannerContext::get_block_from_queue(RuntimeState* 
state, Block* block, b
     *eos = done();
 
     if (_tasks_queue.empty()) {
-        _scan_starving = !done() &&
-                         _num_finished_scanners < 
cast_set<int32_t>(_all_scanners.size()) &&
-                         (_num_scheduled_scanners > 0 || 
!_pending_scanners.empty());
         _dependency->block();
-    } else {
-        _scan_starving = false;
     }
 
     return Status::OK();
@@ -380,7 +369,6 @@ void ScannerContext::stop_scanners(RuntimeState* state) {
         return;
     }
     _should_stop = true;
-    _scan_starving = false;
     _set_scanner_done();
     for (const std::weak_ptr<ScannerDelegate>& scanner : _all_scanners) {
         if (std::shared_ptr<ScannerDelegate> sc = scanner.lock()) {
@@ -463,13 +451,8 @@ void ScannerContext::update_peak_running_scanner(int num) {
 
 int32_t ScannerContext::_get_margin(std::unique_lock<std::mutex>& 
transfer_lock,
                                     std::unique_lock<std::shared_mutex>& 
scheduler_lock) {
-    int32_t target_scan_concurrency = _min_scan_concurrency;
-    if (_scan_starving && _tasks_queue.empty()) {
-        target_scan_concurrency = _max_scan_concurrency;
-    }
-
-    // margin_1 is used to ensure each scan operator could have enough scan 
tasks.
-    int32_t margin_1 = target_scan_concurrency -
+    // margin_1 is used to ensure each scan operator could have at least 
_min_scan_concurrency scan tasks.
+    int32_t margin_1 = _min_scan_concurrency -
                        (cast_set<int32_t>(_tasks_queue.size()) + 
_num_scheduled_scanners);
 
     // margin_2 is used to ensure the scan scheduler could have at least 
_min_scan_concurrency_of_scan_scheduler scan tasks.
@@ -491,11 +474,10 @@ int32_t 
ScannerContext::_get_margin(std::unique_lock<std::mutex>& transfer_lock,
 
     VLOG_DEBUG << fmt::format(
             "[{}|{}] schedule scan task, margin_1: {} = {} - ({} + {}), 
margin_2: {} = {} - "
-            "({} + {}), margin: {}, scan starving: {}",
-            print_id(_query_id), ctx_id, margin_1, target_scan_concurrency, 
_tasks_queue.size(),
+            "({} + {}), margin: {}",
+            print_id(_query_id), ctx_id, margin_1, _min_scan_concurrency, 
_tasks_queue.size(),
             _num_scheduled_scanners, margin_2, 
_min_scan_concurrency_of_scan_scheduler,
-            _scanner_scheduler->get_active_threads(), 
_scanner_scheduler->get_queue_size(), margin,
-            _scan_starving);
+            _scanner_scheduler->get_active_threads(), 
_scanner_scheduler->get_queue_size(), margin);
 
     return margin;
 }
diff --git a/be/src/exec/scan/scanner_context.h 
b/be/src/exec/scan/scanner_context.h
index 857dfb736e9..553408ebc96 100644
--- a/be/src/exec/scan/scanner_context.h
+++ b/be/src/exec/scan/scanner_context.h
@@ -251,8 +251,7 @@ protected:
     // Each scan operator can submit _max_scan_concurrency scanner to 
scheduelr if scheduler has enough resource.
     // So that for a single query, we can make sure it could make full 
utilization of the resource.
     int32_t _max_scan_concurrency = 0;
-    int32_t _min_scan_concurrency = 1;
-    bool _scan_starving = false;
+    MOCK_REMOVE(const) int32_t _min_scan_concurrency = 1;
 
     std::shared_ptr<ScanTask> _pull_next_scan_task(std::shared_ptr<ScanTask> 
current_scan_task,
                                                    int32_t 
current_concurrency);
diff --git a/be/src/exec/scan/scanner_scheduler.cpp 
b/be/src/exec/scan/scanner_scheduler.cpp
index a6d35f3a0b7..c116c354f10 100644
--- a/be/src/exec/scan/scanner_scheduler.cpp
+++ b/be/src/exec/scan/scanner_scheduler.cpp
@@ -397,7 +397,7 @@ int ScannerScheduler::get_remote_scan_thread_queue_size() {
 int ScannerScheduler::default_min_active_scan_threads() {
     return config::min_active_scan_threads > 0
                    ? config::min_active_scan_threads
-                   : config::min_active_scan_threads = 
default_local_scan_thread_num();
+                   : config::min_active_scan_threads = CpuInfo::num_cores() * 
2;
 }
 
 int ScannerScheduler::default_min_active_file_scan_threads() {
diff --git a/be/test/exec/scan/scanner_context_test.cpp 
b/be/test/exec/scan/scanner_context_test.cpp
index 8b2097716de..35156865bb3 100644
--- a/be/test/exec/scan/scanner_context_test.cpp
+++ b/be/test/exec/scan/scanner_context_test.cpp
@@ -423,31 +423,6 @@ TEST_F(ScannerContextTest, get_margin) {
     scanner_context->_num_scheduled_scanners = 20;
     margin = scanner_context->_get_margin(transfer_lock, scheduler_lock);
     ASSERT_EQ(margin, 0);
-
-    // Downstream is waiting for scan data while scheduler is busy. The scan 
operator should
-    // refill up to max scan concurrency instead of being limited by min scan 
concurrency.
-    scheduler = std::make_unique<MockSimplifiedScanScheduler>(cgroup_cpu_ctl);
-    EXPECT_CALL(*scheduler, 
get_active_threads()).WillOnce(testing::Return(50));
-    EXPECT_CALL(*scheduler, get_queue_size()).WillOnce(testing::Return(10));
-    scanner_context->_scanner_scheduler = scheduler.get();
-    scanner_context->_min_scan_concurrency_of_scan_scheduler = 20;
-    scanner_context->_num_scheduled_scanners = 0;
-    scanner_context->_min_scan_concurrency = 1;
-    scanner_context->_max_scan_concurrency = 8;
-    scanner_context->_scan_starving = true;
-    margin = scanner_context->_get_margin(transfer_lock, scheduler_lock);
-    ASSERT_EQ(margin, scanner_context->_max_scan_concurrency);
-
-    // If there is already a produced task waiting in the queue, downstream is 
not scan-starved.
-    scheduler = std::make_unique<MockSimplifiedScanScheduler>(cgroup_cpu_ctl);
-    EXPECT_CALL(*scheduler, 
get_active_threads()).WillOnce(testing::Return(50));
-    EXPECT_CALL(*scheduler, get_queue_size()).WillOnce(testing::Return(10));
-    scanner_context->_scanner_scheduler = scheduler.get();
-    scanner_context->_tasks_queue.push_back(
-            
std::make_shared<ScanTask>(std::make_shared<ScannerDelegate>(scanner)));
-    margin = scanner_context->_get_margin(transfer_lock, scheduler_lock);
-    ASSERT_EQ(margin, 0);
-    scanner_context->_tasks_queue.clear();
 }
 
 TEST_F(ScannerContextTest, pull_next_scan_task) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 34e82825c48..4a7253db60c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -1112,8 +1112,8 @@ public class SessionVariable implements Serializable, 
Writable {
     public long maxScanQueueMemByte = 2147483648L / 20;
 
     @VariableMgr.VarAttr(name = MAX_SCANNERS_CONCURRENCY, needForward = true, 
description = {
-            "ScanNode 扫描数据的最大并发,默认为 8", "The max threads to read data of 
ScanNode, default 8"})
-    public int maxScannersConcurrency = 8;
+            "ScanNode 扫描数据的最大并发,默认为 4", "The max threads to read data of 
ScanNode, default 4"})
+    public int maxScannersConcurrency = 4;
 
     @VariableMgr.VarAttr(name = MAX_FILE_SCANNERS_CONCURRENCY, needForward = 
true, description = {
             "FileScanNode 扫描数据的最大并发,默认为 16", "The max threads to read data of 
FileScanNode, default 16"})


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

Reply via email to