Repository navigation
[perf](load) introduce sequential prefetch for FileScannerV2 CSV reads - #69716
Conversation
### What problem does this PR solve? Issue Number: None Related PR: apache#69333 Problem Summary: After CSV ingestion switched to FileScannerV2, `DelimitedTextReader` opened remote files directly through `FileFactory`, bypassing the sequential prefetch used by the original CSV reader. S3 reads therefore block the scanner instead of overlapping remote I/O with CSV parsing. Restore `DelegateReader::create_file_reader(SEQUENTIAL)` in the shared CSV/Text reader, passing the shared IOContext and the adjusted split range. Unknown-size first splits use an end sentinel that the prefetch reader clamps to the physical file size. Keep tracing outside the prefetch layer and preserve the existing stream-load pipe path. ### Release note Restore asynchronous S3 prefetch for FileScannerV2 CSV and text reads. ### Check List (For Author) - Test - [x] Unit Test added: `CsvV2ReaderTest.S3PrefetchPreservesSplitRowsAndReadStatistics` covers whole-file, mid-row split and unknown-size reads; checks row values, IO statistics and background-thread S3 reads. - Local runtime execution is **blocked**, not passed: `./run-be-ut.sh --run --filter='CsvV2ReaderTest.*' -j 8` stops during JDK initialization with `Failed setting boot class path`. Reproduced outside the sandbox. Runtime validation is pending CI. - Passed repository clang-format 16 formatting/check scripts, `build-support/check-build-hygiene.sh`, and `git diff --check`. - No post-fix throughput or same-host benchmark result is claimed. - Behavior changed: - [x] Yes. Eligible S3 CSV/Text readers use the existing sequential prefetch implementation. No row parsing, schema or stream-pipe semantics change. - Does this need documentation? - [x] No.
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
|
run buildall |
|
/review |
### What problem does this PR solve? Issue Number: None Related PR: apache#69716 Problem Summary: The anonymous-namespace CSV S3 test client uses MOCK_METHOD for operations that never have expectations. Clang reports the generated gmock_* member functions as unused, and BE unit-test compilation fails under -Werror. Replace these unused mock methods with ordinary virtual overrides that fail the test and return unsupported status on unexpected calls. Remove the unused gMock include. ### Release note None ### Check List (For Author) - Test: reproduced the original diagnostic and passed the corrected client in a focused Clang 16 syntax check using actual repository headers and -Werror -Wunused-member-function; repository format and hygiene checks. Full BE unit-test execution remains blocked by local JDK initialization. - Behavior changed: No production behavior change. - Does this need documentation: No.
|
run buildall |
|
/review |
There was a problem hiding this comment.
Request changes: three P1 findings affect cached-read concurrency, timed-out reader ownership, and configured buffer-ring geometry; one P2 finding leaves the new prefetch profile counters at zero. All four are inline. There were no existing inline comments or blocking IDs to carry forward.
Static coverage includes both changed files and the scanner/table-reader -> CSV/Text -> DelegateReader -> S3/cache -> line-reader chain. Critical checkpoint conclusions:
- Goal and proof: eligible S3 CSV/Text now selects sequential prefetch. The added unit test checks representative rows, split alignment, unknown size, outer read statistics and background GET dispatch, but does not establish concurrency or timeout safety.
- Scope, clarity and reuse: the production change is small and reuses the legacy CSV delegate. Layer ownership and schema/materialization boundaries remain intact. Reuse exposes the three safety defects reported inline.
- Concurrency and locks: the default buffer ring schedules four workers sharing non-atomic scanner cache counters without a common update/snapshot lock; the scanner's monotonicity assertions make this a crash risk. Outer tracing counters remain on the scanner thread. No new lock-order cycle was found.
- Lifecycle and memory: normal close drains active reads and prefetch backing buffers allocate/free on the query thread. Timed-out close can release scanner-owned context pointees while work remains active. No new static initialization dependency or ownership cycle was found; no separate orphan-memory defect was substantiated.
- Configuration: no configuration is added. Existing mutable prefetch size and wait-time settings now affect this v2 path; a supported value of 6 MiB exposes invalid buffer indexing. Runtime mutation is observed when each reader is constructed.
- Compatibility: no wire definition, function symbol, storage format or persistent metadata changes. No Thrift/Protobuf or rolling-upgrade compatibility change applies.
- Parallel paths: CSV and Text share the change; FILE_STREAM retains its pipe path. Local/HDFS/Broker/HTTP pass through the delegate. Default small raw S3 objects use DelegateReader's existing InMemory policy; cached S3 uses prefetch. Compressed first splits preserve their physical-byte/decompressor contract and non-first compressed splits remain rejected.
- Conditional logic and correctness: adjusted pre-read prefixes preserve the split end; unknown-size sentinel clamps to physical S3 size; synchronous fallback beyond the prefetch range preserves records crossing split boundaries. Backward delimiter probes were rechecked. No additional default-configuration row-correctness defect was found.
- Tests and expected results: the mock uses immutable data and atomic counters; cleanup restores global test state. Existing local CSV tests cover delimiters, headers, projection, malformed input, multiple blocks and small split boundaries. No expected-result artifact is changed. Tests were inspected, not executed.
- Observability: outer FileReaderStats remains available, but newly registered prefetch counters are never published, as reported inline.
- Transactions and persistence: no transaction, visibility-version, delete-bitmap, EditLog, data-write atomicity or crash-recovery logic changes.
- FE-BE propagation: no new cross-process variable or transmission path applies.
- Performance: asynchronous dispatch is present and existing buffering is reused; throughput, overlap benefit, allocation behavior and read amplification were not measured. No benchmark result is claimed.
- Further-issue sweep and user focus: both changed paths and all risk items were reviewed beyond the initial findings. No additional user focus was supplied; no unresolved static candidate remains.
Validation limits: this contract permits static review only, so no build, unit/regression test, sanitizer run or benchmark was performed. The added tiny fixture disables file cache, forces the prefetch path, uses one worker and ends known-size splits at EOF. Runtime coverage remains missing for cached/concurrent multi-buffer reads, the 4 MiB rotation boundary and non-default sizes, errors/timeouts/early close/cancellation, finite split-end overread, default small-file dispatch and compressed/Text S3 integration. These are disclosed validation gaps, not claims of passing execution.
Review converged after 3 round(s).
### What problem does this PR solve? Issue Number: None Related PR: apache#69716 Problem Summary: Sequential prefetch exposes shared cache statistics to concurrent updates and can outlive scanner-owned state after a close timeout. Give each buffer separate cache statistics and merge them on the consumer thread. Drain active reads during close, normalize ring capacity to allocated buffers, and publish CSV/Text prefetch profiles before releasing filesystem readers. Preserve shared stream-pipe ownership. ### Release note Prevent cache-statistics races and shutdown lifetime errors during sequential prefetch. Handle non-multiple-of-four buffer settings and publish CSV/Text prefetch counters. ### Check List (For Author) - Test: Add concurrent-statistics, timeout cleanup, ring-capacity, profile and stream-ownership unit coverage. Buffered-reader test TU passes Clang 16 syntax checking with -Werror -Wunused-member-function. Formatting, hygiene and diff checks pass. Full BE unit execution is blocked by local JDK initialization; production/Csv test syntax checks also encounter local toolchain/generated header incompatibilities. Runtime validation remains pending CI. - Behavior changed: Yes; close drains active I/O, counters merge on the consumer, and the prefetch ring uses its allocated capacity. - Does this need documentation: No
|
run buildall |
|
/review |
|
Codex automated review failed and did not complete. Error: workspace routing discovery unauthorized (401) Please inspect the workflow logs and rerun the review after the underlying issue is resolved. |
TPC-H: Total hot run time: 28727 ms |
TPC-DS: Total hot run time: 151836 ms |
ClickBench: Total hot run time: 24.37 s |
BE UT Coverage ReportIncrement line coverage Increment coverage report
|
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
BE Regression && UT Coverage ReportIncrement line coverage Increment coverage report
|
|
PR approved by anyone and no changes requested. |
|
PR approved by at least one committer and no changes requested. |
### What problem does this PR solve? Issue Number: None Related PR: #69716 Problem Summary: After restoring sequential prefetch, large V2 CSV loads still spend substantial CPU time in row parsing and string materialization. The reader compares a general separator at every byte, updates atomic profile counters per cell, starts three stage timers per row, and repeats checked string-column casts per cell. It also ignores the row cap supplied by TableReader. This change combines four optimizations on master: - Compare the separator byte directly for plain single-character separators; retain enclosed, multi-character, Hive/OpenCSV and PROTO parsing paths. - Accumulate exact work counters locally and publish at get_block/count/schema return, including errors. Sample stage timings every 1024 physical read_line calls, starting with the first, and expose unscaled SampledReadLineTime, SampledSplitLineTime and SampledDeserializeTime with sample counts. DelimitedTextReader remains full elapsed time; split-prefix alignment has its own full timer. - Validate nullable string column types and reserve offsets/null maps once per mutable batch, then insert strings directly with the existing NULL, quoting and escape semantics. - Honor FileReader::set_batch_size, retaining the existing byte budget and runtime default when no explicit cap is supplied. The caller still controls the maximum batch size; this does not force 16352-row blocks. Shared counters and batch sizing also apply to the Hive text reader. ### Performance benchmark On TPC-DS SF100, elapsed time decreased from **1,944 seconds to 1,375 seconds**: | Benchmark | Before | After | Time reduction | Speedup | | --- | ---: | ---: | ---: | ---: | | TPC-DS SF100 | 1,944 s | 1,375 s | 29.3% (569 s) | 1.41× | ### Release note Reduce V2 CSV parsing overhead and honor caller-provided batch sizes. Delimited-text per-stage profile timers are now explicitly named Sampled* and contain unscaled sampled durations; use the full DelimitedTextReader timer for elapsed-time comparisons. ### Check List (For Author) - Test - [x] Unit Test: added cases for dynamic/zero batch caps, byte limits, filtered blocks, cross-batch sampling and exact counters, single/multi-character separators, NULL and escape behavior, missing fields, reordered projection and copy-on-write. Extended error, rejected-row and COUNT counter coverage. - Execution: run-be-ut.sh was attempted with CsvV2ReaderTest.*, TextV2ReaderTest.* and LegacyAndV2/PlainCsvSplitTest.*. It exits before C++ compilation because the local JDK 17 fails to initialize (Failed setting boot class path), including outside the sandbox. Full build/UT remain pending. Performance benchmark results are reported above. - Passed: repository clang-format 16 formatting/check scripts, build-support/check-build-hygiene.sh and git diff --check. - Behavior changed: Yes. Existing batch-size contract is honored, and detailed stage timers are explicitly sampled. CSV value semantics are unchanged. - Does this need documentation: No. The profile includes a timing explanation; no new configuration or SQL syntax. For further benchmark comparisons, use identical hardware, input, compression, cache conditions and load batch/byte-budget settings for the parent and this commit. Compare total load time, Scanner CPU time, DelimitedTextReader time and RowsRead/BlockNumber. Do not directly compare Sampled* timers with the previous full stage timers.
What problem does this PR solve?
Issue Number: None
Related PR: #69333
Problem Summary:
After CSV ingestion switched to FileScannerV2,
DelimitedTextReaderopened remote files directly throughFileFactory, bypassing the sequential prefetch used by the original CSV reader. S3 reads therefore block the scanner instead of overlapping remote I/O with CSV parsing.Restore
DelegateReader::create_file_reader(SEQUENTIAL)in the shared CSV/Text reader, passing the shared IOContext and adjusted split range. Unknown-size first splits use an end sentinel bounded by the physical file size. Tracing remains outside the prefetch layer, and shared stream-load pipes retain their existing ownership and cancellation behavior.To safely integrate asynchronous reads with V2 scanner statistics:
buffered_reader_read_timeout_mswhile an underlying request is outstanding.Performance
For the TPC-H dataset load benchmark, elapsed time decreased from 2617.33 s to 1696.06 s, saving 921.27 s. This is a 35.2% reduction in load time, or approximately 1.54x speedup, for the measured workload.
Release note
Restore asynchronous S3 prefetch for FileScannerV2 CSV and text reads, with safe cache-statistics aggregation and cleanup, consistent ring capacity and populated prefetch profiles.
Check List (For Author)
Test:
buffered_reader_test.cpptranslation unit against repository and installed third-party headers with-Werror -Wunused-member-function.build-support/check-build-hygiene.sh, andgit diff --check../run-be-ut.sh --run --filter='BufferedReaderTest.*:CsvV2ReaderTest.*' -j 8stops at JDK initialization (Failed setting boot class path). Separate production/CSV syntax attempts encounter installed C++ library and stale generated-header incompatibilities. No compilation database is available for clang-tidy. Runtime and sanitizer validation remain pending CI.FileCacheStatistics. No cached-S3 end-to-end runtime result is claimed.Behavior changed:
Does this need documentation?
Check List (For Reviewer who merge this PR)