mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-09-24 06:05:36 +00:00
perf(servers): coalesce ready Flight record batches (#9167)
* perf(servers): prototype ready-only Flight batch coalescing Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * fix(servers): bound ready Flight batch admission and cover lifecycle Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * test(servers): fix redundant error pattern assertion Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * refactor(servers): simplify Flight coalescing with append-then-check accumulator Remove the lookahead/pending machinery and coalesce with an append-then-check soft budget. Extract the group state into a private BatchAccumulator so the ordinary stream loop reads as a short control flow: append each ready batch, flush when a budget is reached. Budgets are flush thresholds, not memory limits, so a group may exceed a budget by the final appended batch. First-batch direct send and singleton passthrough for a batch that starts a group already at a budget are unchanged. Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * refactor(servers): split Flight stream into dispatcher and per-path units FlightRecordBatchStream::flight_data_stream held two large side-by-side branches (the verbose/ANALYZE metrics path and the plain/coalescing path) inline, making the function hard to read. Split it into a small dispatcher that keeps only the shared prologue (schema send, metrics init) and the shared EOF final-metrics tail, and move each branch into a self-contained unit: - verbose path -> Self::verbose_metrics_stream - plain/coalescing path -> private CoalescingBatcher (owns the BatchAccumulator, sent_first_batch, and schema) Each path returns whether it reached normal EOF; the dispatcher skips the shared final-metrics tail on any early error/failed-send exit, preserving the exact pre-split behavior (an early return previously exited the whole function and bypassed the tail). No behavior, metrics ordering, or coalescing semantics change. Add a regression test that drives flight_data_stream directly and asserts the verbose error path does not invoke the final-metrics tail (producer-side metrics() call count), since the public message stream hides the tail after an error. Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * docs(servers): describe Flight stream units by behavior, not refactor history Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * perf(servers): avoid copying over-budget batches and release merged inputs Three review-driven improvements to Flight batch coalescing: - After a successful merge, reuse the drained vector in place (clear + push the merged batch) so the source batches are dropped before the send loop instead of staying alive across a backpressured send. - A batch that is itself at/over a budget is forwarded as a singleton even when encountered inside an accumulation group: the accumulated group is flushed and sent first, then the over-budget batch. This avoids copying a large batch into an aggregate just to merge the small batches ahead of it. Under-budget append-then-check is unchanged (600+600 still merges). - Strengthen two tests: the first-batch test now drives the producer directly and asserts the upstream poll count is exactly one at the first-batch send; the dictionary test now decodes the merged dictionary keys to assert the logical values, so a key-remapping regression is caught. Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * perf(servers): raise Flight coalesce row budget to 4096 mito2 commonly emits ~2000-row batches (~32-94KiB), so a 1024-row budget marked every such batch oversized and the coalescer forwarded them unbatched. Measured on a local distributed cluster (2M-row table): - full selector: 1000 -> 337 batches, p50 latency 4133 -> 3316 ms (-20%) - range scan: 501 -> 206 batches, 1466 -> 1162 ms (-21%) - small/olap queries (single-series, top-k, group-by): unchanged Larger budgets (8192 rows, or 1-4MiB bytes) coalesce more batches but do not improve latency further and slightly regress it, so 4096 rows is the sweet spot; MAX_BYTES stays at 256KiB and MAX_BATCHES at 16. Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> --------- Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
This commit is contained in: