Exp 136: completion-side reader-handler scheduling counter#113
Open
danReynolds wants to merge 4 commits into
Open
Exp 136: completion-side reader-handler scheduling counter#113danReynolds wants to merge 4 commits into
danReynolds wants to merge 4 commits into
Conversation
Add profile-mode counters (`completion_handler_us` / `completion_handler_count` in the reader worker port handler, and `stream_emit_us` / `stream_emit_count` in `StreamEntry.emit`) that expose the main-isolate reader-completion path on stream-fanout workloads. Because `_WorkerSlot.request` uses `Completer<Object?>.sync()`, the reader-pool worker port handler captures the whole `_dispatch` resume / `_requery` continuation / `entry.emit` / `_flushQueue` chain in one synchronous bracket. `audit_workloads.dart` gains an optional `countersAfterDrain` snapshot and switches A11c's fixed-50ms drain to the same quiet-window pattern keyed-PK already uses, so reader-completion work that fires after the writer-burst stopwatch is captured. Existing exp 119 / 121 audits keep the burst-end `counters` field unchanged. A new harness `benchmark/profile/completion_scheduling_audit.dart` formats the A11c (baseline / disjoint / overlap) + keyed-PK report. On A11c overlap the reader-completion chain is 22-27% of total wall (burst + drain) at ~12 us per call across ~3,700-3,900 calls per burst; 99.2% of those replies short-circuit via `selectIfChanged` hash, so subscriber-fanout emit is < 1% of the chain. On keyed-PK the same path is 4-5% of total wall. On A11c disjoint it is 0% (exp 106 column elision blocks every re-query). Closes the `completion-side microtask scheduling cost counter` entry in `signals.json#stream-rerun-dispatch.blockedOnMeasurement` and makes reader-reply batching the bounded implementation candidate that follows. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Measurement-only experiment that adds profile-mode counters for the main-isolate reader-completion handler chain (completion_handler_us/count) and StreamEntry.emit fanout (stream_emit_us/count), plus a new audit harness to read them. Concludes that reader-completion handling is 22–27% of A11c overlap total wall, making reader-reply batching the next bounded candidate; subscriber fanout (<1%) is not.
Changes:
- Add four
ProfileCountersfields and instrument_WorkerSlotnormal-reply branch andStreamEntry.emitunderkProfileMode. - Extend
audit_workloads.dartwith an optional post-drain counters snapshot and switch A11c drain to the quiet-window pattern. - Add
completion_scheduling_audit.dartharness, aggregate result, experiment writeup, journal entries, and signals.json bookkeeping (closes the blockedOnMeasurement entry, archives 119, adds exp 136 to keyPriors).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| lib/src/profile_counters.dart | Adds four completion/emit counters with snapshot+reset wiring |
| lib/src/reader/reader_pool.dart | Wraps normal-reply handler body in profile-mode stopwatch |
| lib/src/stream_engine.dart | Wraps StreamEntry.emit fanout loop in profile-mode stopwatch |
| benchmark/profile/audit_workloads.dart | Adds countersAfterDrain/drainUs and quiet-window A11c drain |
| benchmark/profile/completion_scheduling_audit.dart | New harness rendering the markdown report |
| benchmark/profile/results/exp-136-completion-scheduling-aggregate.md | Committed pass-d aggregate report |
| experiments/136-completion-microtask-counter.md | Experiment writeup with hypothesis/results/decision |
| experiments/JOURNAL.md | Two new lessons (drain-snapshot timing, worktree pub get) |
| experiments/README.md | Adds exp 136 to In Review row |
| experiments/signals.json | Updates currentRead/keyPriors/archive/blockedOnMeasurement; adds exp 136 entry |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI caught that the snapshot/diff/reset test asserted on the exact key set, which exp 136 widened. Add the four new keys to the existing expectations and add a round-trip test for the completion counters. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hypothesis
After exp 120 and exp 121,
signals.json#stream-rerun-dispatch.blockedOnMeasurementlisted two named gating measurements: writer-isolate wall split (handled by in-flight exp 135) and completion-side microtask scheduling cost counter (this PR). On A11c overlap, the bulk of remaining main-isolate wall should land in the reader worker port handler chain. Building the counter resolves the entry — accepts the area if the fraction is large, or rules it out if small.Approach
ProfileCountersgains four main-isolate fields:completionHandlerUs/completionHandlerCount(reader-pool worker port handler synchronous body) andstreamEmitUs/streamEmitCount(StreamEntry.emitsubscriber-fanout loop). Since_WorkerSlot.requestusesCompleter<Object?>.sync(), the handler counter captures the whole_dispatchresume /_requerycontinuation /entry.emit/_flushQueuechain in one stopwatch.audit_workloads.dartgains an optionalcountersAfterDrainsnapshot and switches A11c's fixed-50ms drain to the same quiet-window pattern keyed-PK already uses. Existing exp 119 / exp 121 audits ignore the new field and continue using the burst-endcounters.benchmark/profile/completion_scheduling_audit.dartformats the A11c (baseline / disjoint / overlap) + keyed-PK report.Results
Four repeated passes; aggregate at
benchmark/profile/results/exp-136-completion-scheduling-aggregate.md. Pass-d numbers shown; other passes match the same band.Reader-completion chain is the largest reachable main-isolate slice on A11c overlap. 99.2% of 3,700–3,900 replies per burst short-circuit via
selectIfChangedhash (28–31 actual subscriber emits), so subscriber-fanout is not the cost — per-call wall is bootstrap-shaped (Future resolution + hash check +_flushQueueadmit). On disjoint the counter is 0 because exp 106 column elision blocks every re-query; on keyed-PK absolute completion wall is 11 ms.dispatcher_parked_total = 0,dispatcher_wake_retry_total = 0, anddispatcher_max_parked_concurrent = 0on every workload — exp 120 / exp 122 hold post-instrumentation.Outcome
Accepted — measurement. Closes the
completion-side microtask scheduling cost counterentry insignals.json#stream-rerun-dispatch.blockedOnMeasurement. Makes reader-reply batching the bounded implementation candidate that follows; a future experiment in that direction must dropcompletion_us / total_uson A11c overlap and stay neutral on disjoint and keyed-PK (otherwise the release-suite delta is workload-specific). After this lands together with in-flight exp 135 (writer-isolate split), thestream-rerun-dispatch.blockedOnMeasurementarray is empty.Test plan
dart analyze --fatal-infoson edited files (profile_counters.dart,stream_engine.dart,reader_pool.dart,audit_workloads.dart,completion_scheduling_audit.dart) — clean.dart test test/database_test.dart— 47/47 pass.dart test test/stream_test.dart test/stream_invalidation_coalescing_test.dart test/stream_dependency_shapes_test.dart— pass.dart run -DRESQLITE_PROFILE=true benchmark/profile/invalidation_traversal_audit.dart— exp 121's audit still produces in-band numbers (invalidate 14.7% of overlap burst wall).dart run -DRESQLITE_PROFILE=true benchmark/profile/completion_scheduling_audit.dart --markdown— four passes, aggregate committed.🤖 Generated with Claude Code