Repository navigation
[feature](executor) Add the time-sharing executor framework and use it in the scanner section. - #51690
Conversation
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
run buildall |
a41436a to
36e6551
Compare
|
run buildall |
1 similar comment
|
run buildall |
05fa082 to
ace919d
Compare
|
run buildall |
ace919d to
7dbf1d1
Compare
|
run buildall |
7dbf1d1 to
0a21731
Compare
|
run buildall |
0a21731 to
6898e1b
Compare
|
run buildall |
6898e1b to
cfb5444
Compare
|
run buildall |
cfb5444 to
b98871e
Compare
|
run buildall |
b98871e to
0ec00f6
Compare
|
run buildall |
0ec00f6 to
8f8daca
Compare
|
run buildall |
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
|
run buildall |
TPC-H: Total hot run time: 34240 ms |
TPC-DS: Total hot run time: 187422 ms |
ClickBench: Total hot run time: 30.6 s |
4942541 to
82a3076
Compare
|
run buildall |
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
ok |
4ee29a5 to
d752709
Compare
|
run buildall |
TPC-H: Total hot run time: 34563 ms |
TPC-DS: Total hot run time: 191448 ms |
ClickBench: Total hot run time: 32.68 s |
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
|
PR approved by at least one committer and no changes requested. |
|
PR approved by anyone and no changes requested. |
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
…cs with other thread pool (#54910) Related PR: #51690 TimeSharingTaskExecutor is using a individual metrics name called `doris_be_split_thread_pool_xxxx`, this is miss leading. TimeSharingTaskExecutor is actually a specialized ThreadPool, which uses a time_sharing queuing policy. We want to use `doris_be_thread_pool_xxx` to record its metrics.
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. Making the thread pool path the default exposed one scheduling gap between the two admission paths. apache#65814 stops the TaskExecutor path (`ScannerContext::_pull_next_scan_task`) from submitting pending scanners once the shared scan LIMIT is exhausted while a completed or in-flight task can still wake the operator. The thread pool admission rewritten in apache#67070 (`ScannerContext::can_admit_scan_task`) does not apply this rule, so for a `SELECT ... LIMIT n` over many tablets every remaining pending scanner would still be admitted and run `prepare()`/`open()` (tablet reader init) only to report EOS right away. The same rule is now applied in `can_admit_scan_task`, including the existing escape that admits one pending scanner when nothing else can wake the pipeline task. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans) and `ScannerContextTest.thread_pool_admission_stops_after_shared_limit` (fails without the admission fix); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. Making the thread pool path the default exposed one scheduling gap between the two admission paths. apache#65814 stops the TaskExecutor path (`ScannerContext::_pull_next_scan_task`) from submitting pending scanners once the shared scan LIMIT is exhausted while a completed or in-flight task can still wake the operator. The thread pool admission rewritten in apache#67070 (`ScannerContext::can_admit_scan_task`) does not apply this rule, so for a `SELECT ... LIMIT n` over many tablets every remaining pending scanner would still be admitted and run `prepare()`/`open()` (tablet reader init) only to report EOS right away. The same rule is now applied in `can_admit_scan_task`, including the existing escape that admits one pending scanner when nothing else can wake the pipeline task. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans) and `ScannerContextTest.thread_pool_admission_stops_after_shared_limit` (fails without the admission fix); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. Making the thread pool path the default exposed one scheduling gap between the two admission paths. apache#65814 stops the TaskExecutor path (`ScannerContext::_pull_next_scan_task`) from submitting pending scanners once the shared scan LIMIT is exhausted while a completed or in-flight task can still wake the operator. The thread pool admission rewritten in apache#67070 (`ScannerContext::can_admit_scan_task`) does not apply this rule, so for a `SELECT ... LIMIT n` over many tablets every remaining pending scanner would still be admitted and run `prepare()`/`open()` (tablet reader init) only to report EOS right away. The same rule is now applied in `can_admit_scan_task`, including the existing escape that admits one pending scanner when nothing else can wake the pipeline task. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans) and `ScannerContextTest.thread_pool_admission_stops_after_shared_limit` (fails without the admission fix); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. Making the thread pool path the default exposed one scheduling gap between the two admission paths. apache#65814 stops the TaskExecutor path (`ScannerContext::_pull_next_scan_task`) from submitting pending scanners once the shared scan LIMIT is exhausted while a completed or in-flight task can still wake the operator. The thread pool admission rewritten in apache#67070 (`ScannerContext::can_admit_scan_task`) does not apply this rule, so for a `SELECT ... LIMIT n` over many tablets every remaining pending scanner would still be admitted and run `prepare()`/`open()` (tablet reader init) only to report EOS right away. The same rule is now applied in `can_admit_scan_task`, including the existing escape that admits one pending scanner when nothing else can wake the pipeline task. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans) and `ScannerContextTest.thread_pool_admission_stops_after_shared_limit` (fails without the admission fix); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. Making the thread pool path the default exposed one scheduling gap between the two admission paths. apache#65814 stops the TaskExecutor path (`ScannerContext::_pull_next_scan_task`) from submitting pending scanners once the shared scan LIMIT is exhausted while a completed or in-flight task can still wake the operator. The thread pool admission rewritten in apache#67070 (`ScannerContext::can_admit_scan_task`) does not apply this rule, so for a `SELECT ... LIMIT n` over many tablets every remaining pending scanner would still be admitted and run `prepare()`/`open()` (tablet reader init) only to report EOS right away. The same rule is now applied in `can_admit_scan_task`, including the existing escape that admits one pending scanner when nothing else can wake the pipeline task. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans) and `ScannerContextTest.thread_pool_admission_stops_after_shared_limit` (fails without the admission fix); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. With the thread pool path as the default, a `SELECT ... LIMIT n` over many tablets keeps admitting its remaining pending scanners after peer scanners have exhausted the shared scan LIMIT (`ScannerContext::can_admit_scan_task`, rewritten in apache#67070, only applies the concurrency limit). Admission is kept that way on purpose: holding pending scanners back based on the in-flight or completed task counters, as apache#65814 does on the TaskExecutor path, ties the schedule to bookkeeping that is easy to get wrong and can leave a context with nothing to wake the operator. Instead, `Scanner::get_block_after_projects()` now checks the shared LIMIT before it reads: once the counter is exhausted, the scanner returns an empty block with EOS, so an admitted scanner never reads its range for rows the operator will cut anyway. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans), `ScannerContextTest.thread_pool_admission_ignores_shared_limit` (a pending scanner is still admitted after the shared LIMIT is exhausted while tasks are in flight or completed) and `ScannerProjectionTest.shared_limit_exhausted_before_call_reports_eos_without_reading` (the admitted scanner reports EOS with an empty block without reading); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*`, `ScannerProjectionTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. With the thread pool path as the default, a `SELECT ... LIMIT n` over many tablets keeps admitting its remaining pending scanners after peer scanners have exhausted the shared scan LIMIT (`ScannerContext::can_admit_scan_task`, rewritten in apache#67070, only applies the concurrency limit). Admission is kept that way on purpose: holding pending scanners back based on the in-flight or completed task counters, as apache#65814 does on the TaskExecutor path, ties the schedule to bookkeeping that is easy to get wrong and can leave a context with nothing to wake the operator. Instead, `Scanner::get_block_after_projects()` now checks the shared LIMIT before it reads: once the counter is exhausted, the scanner returns an empty block with EOS, so an admitted scanner never reads its range for rows the operator will cut anyway. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans), `ScannerContextTest.thread_pool_admission_ignores_shared_limit` (a pending scanner is still admitted after the shared LIMIT is exhausted while tasks are in flight or completed) and `ScannerProjectionTest.shared_limit_exhausted_before_call_reports_eos_without_reading` (the admitted scanner reports EOS with an empty block without reading); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*`, `ScannerProjectionTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: apache#51690, apache#58144, apache#58273, apache#65814, apache#67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in apache#58273; the internal-table default was already reverted once in apache#58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. With the thread pool path as the default, a `SELECT ... LIMIT n` over many tablets keeps admitting its remaining pending scanners after peer scanners have exhausted the shared scan LIMIT (`ScannerContext::can_admit_scan_task`, rewritten in apache#67070, only applies the concurrency limit). Admission is kept that way on purpose: holding pending scanners back based on the in-flight or completed task counters, as apache#65814 does on the TaskExecutor path, ties the schedule to bookkeeping that is easy to get wrong and can leave a context with nothing to wake the operator. Instead, `Scanner::get_block_after_projects()` now checks the shared LIMIT before it reads: once the counter is exhausted, the scanner returns an empty block with EOS, so an admitted scanner never reads its range for rows the operator will cut anyway. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool` (registered defaults are `false` and the workload group creates thread pool schedulers for local and remote scans), `ScannerContextTest.thread_pool_admission_ignores_shared_limit` (a pending scanner is still admitted after the shared LIMIT is exhausted while tasks are in flight or completed) and `ScannerProjectionTest.shared_limit_exhausted_before_call_reports_eos_without_reading` (the admitted scanner reports EOS with an empty block without reading); ran `WorkloadGroupManagerTest.*`, `ScannerContextTest.*`, `ScannerProjectionTest.*` and other scanner/scheduler/task-executor UTs - Regression test: ran existing suites on a local cluster with the new default: correctness_p0/test_shared_scan_limit_pending_tasks, query_p0 limit pushdown suites, query_p0/scan_range, and stream load CSV suites - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
### What problem does this PR solve? Issue Number: None Related PR: #51690, #58144, #58273, #65814, #67070 Problem Summary: Workload groups pick the scan scheduler for internal and external table scans from `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table`. Both configs currently default to `true` on master, so every workload group creates `TaskExecutorSimplifiedScanScheduler` (the time-sharing task executor) for local (`ls_*`) and remote (`rs_*`) scans. The time-sharing executor is still maturing (for example the self-deadlock fixed in #58273; the internal-table default was already reverted once in #58144), so the default should be the `ThreadPoolSimplifiedScanScheduler` for both internal and external tables. This change sets both configs' default values to `false`. The task executor can still be enabled explicitly through `be.conf`. Making the thread pool path the default exposed four gaps. 1. Pending scanners after an exhausted shared LIMIT. For a `SELECT ... LIMIT n` over many tablets, the thread pool admission (`ScannerContext::can_admit_scan_task`, rewritten in #67070) keeps admitting the remaining pending scanners after peer scanners have exhausted the shared scan LIMIT. Admission is kept that way on purpose: holding pending scanners back based on the in-flight or completed task counters, as #65814 does on the TaskExecutor path, ties the schedule to bookkeeping that is easy to get wrong and can leave a context with nothing to wake the operator. Instead, `Scanner::get_block_after_projects()` now checks the shared LIMIT before it reads: once the counter is exhausted, the scanner returns an empty block, so an admitted scanner never reads its range for rows the operator will cut anyway. It does not report EOS for that: EOS means the underlying read is exhausted, while the LIMIT is applied by the scan operator, which stops the scanners after `reached_limit()`; `ScannerContext::get_block_from_queue()` also finishes the context once the counter is exhausted with nothing in flight. The two pre-existing checks in `Scanner::get_block()` that set `eof` from the shared counter are removed for the same reason, so the shared LIMIT is handled in one place. 2. Rows held in scanner padding under a shared LIMIT. `Scanner::get_block()` charges the shared LIMIT counter as soon as rows pass the filters, but with projections `get_block_after_projects()` may keep a small block in `_padding_block` and emit a later block first. Once peer scanners exhaust the counter, the context reaches EOS without running that scanner again, and the charged rows it holds are lost; for example, a parallel projected `LIMIT 4096` could return 4086 rows. The counter is now decremented only by the rows a call actually returns, so held padding is never charged and the counter equals "LIMIT minus returned rows" between calls. The padding batch target is capped by the remaining LIMIT when a call starts, so a scanner does not read on just to fill half a batch when fewer rows are needed, and the read loop stops as soon as peers exhaust the LIMIT, returning the rows it already holds. Projected scans with selective filters keep coalescing small blocks. The scan does not cap its output at the LIMIT (the operator cuts extra rows), so no further accounting is needed. 3. Exceptions in the row-ID fetch RPC callback. `multiget_data_v2` submits its callback to the remote scan scheduler; on a `ThreadPool` worker there is no exception boundary, and `RowIdStorageReader::read_by_rowids()` constructs `SlotDescriptor(pslot)` before its local `try`, so an unknown `PTypeNode.type` would throw `doris::Exception` and terminate the BE. The callback now calls `RowIdStorageReader::read_by_rowids_for_rpc()`, which converts a thrown exception into an error status on the response before the closure completes the RPC. `ExecEnv::set_id_manager()` is added under `BE_TEST` for the unit test. 4. The shared LIMIT pointer of a scanner initialized while the counter is negative. `ScanLocalState::shared_scan_limit_ptr()` returned null whenever the live counter was negative, and `Scanner::init()` caches that pointer once. Concurrent scanners can return more than the LIMIT before the operator makes its final cut, leaving the counter negative, so a scanner whose local state opened at that moment never checked or charged the shared LIMIT and could read a long selective tail after peers had satisfied the query. The pointer is now returned whenever the operator has a SQL LIMIT, which is how `ScannerContext` already decides it. ### Release note The BE configs `enable_task_executor_in_internal_table` and `enable_task_executor_in_external_table` now default to `false`; internal and external table scans use the thread pool scan scheduler by default. ### Check List (For Author) - Test: - Unit Test: added `WorkloadGroupManagerTest.DefaultScanSchedulersUseThreadPool`, `ScannerContextTest.thread_pool_admission_ignores_shared_limit`, `ScannerProjectionTest.shared_limit_exhausted_before_call_returns_empty_block_without_eos`, `ScannerProjectionTest.shared_limit_counts_only_emitted_rows`, `ScannerProjectionTest.shared_limit_drops_padding_after_peer_satisfies_limit`, `ScannerProjectionTest.shared_limit_flushes_padding_before_reading_more`, `ScannerProjectionTest.shared_limit_flushes_merged_padding_at_limit`, `ScannerProjectionTest.shared_limit_counts_returned_rows_without_projection`, `ScannerProjectionTest.shared_limit_counts_returned_rows_without_padding`, `ScannerProjectionTest.shared_limit_keeps_padding_small_blocks`, `ScannerProjectionTest.shared_limit_exhausted_by_own_rows_stops_reading_without_eos`, `ScannerProjectionTest.shared_limit_exhausted_by_peer_mid_read_returns_held_rows_without_eos`, `ScannerProjectionTest.shared_limit_observed_by_scanner_initialized_under_negative_counter`, `ScannerProjectionTest.no_shared_limit_without_sql_limit` and `RowIdStorageReaderTest.RpcHelperReportsThrownExceptionOnThreadPoolPath` (runs the RPC helper on a real `ThreadPoolSimplifiedScanScheduler`; the test process aborts without the fix); ran `ScannerProjectionTest.*`, `ScannerContextTest.*`, `ScannerLateArrivalRfTest.*`, `WorkloadGroupManagerTest.*`, `RowIdStorageReaderTest.*`, `SubmitExternalScanTasksTest.*` - Regression test: ran on a local cluster with the new default: query_p0/limit (19 suites) and correctness_p0/test_shared_scan_limit_pending_tasks - Behavior changed: Yes (default scan scheduler for internal and external table scans changes from the task executor to the thread pool; it can be switched back via the two BE configs) - Does this need documentation: No
What problem does this PR solve?
Problem Summary:
When concurrent large queries occupy all resources, small queries become hungry and run very slowly.
Release note
In order to solve the problem that when concurrent large queries occupy all resources, small queries become hungry and run very slowly.
A dynamic multi-level priority scheduling is introduced.
The time-sharing executor framework is implemented. Source code in
be/src/vec/exec/executorandbe/src/vec/exec/executor/time_sharingCurrently, this mechanism is used in the scanner, and will be used in the computing layer in the future. Time-sharing executor framework framework currently have options for automatic scheduling and concurrency control. Since the current implementation of the scanning part relies on manual scheduling and already has the ability of concurrency control, the automatic scheduling and concurrency control of the framework should be turned off when integrating the scanning part. Also keep the original implementation of scanner scheduler. Controlled by
enable_task_executor_in_internal_tableandenable_task_executor_in_external_table.A task executor simulator is introduced。By controlling the total number of tasks, the number of concurrency, the number of splits of each task, and the splits generated by different generators of splits (Leaf and Intermediate) (for example, different rates, different waiting times, etc.), we can simulate scenarios and observe relevant performance indicators. In order to compare with the scenario before the code was modified, a test fifo queue was introduced to compare with the current multi-level priority queue.
be/src/vec/exec/executor/simulator.task_executor_simulator/conf/experiment_starve_slow_splits.jsonTask Executor Simulator Performance Results
A system is constructed that first generates many slow splits to simulate the situation of concurrent large queries, and then executes fast splits to simulate the situation of small queries.
task_executor_simulator/conf/experiment_starve_slow_splits.jsonFrom the results, the multi-level priority queue is the first-in-first-out queue in terms of the task completion rate of fast leaf, while the task completion rates of the middle and slow leaf are not as good as the first-in-first-out queue.
Multi-level Priority Queue
Fast Leaf
Intermediate
Slow Leaf
FIFO Queue
Fast Leaf
Intermediate
Slow Leaf
Check List (For Author)
Test
Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)