Repository navigation
perf(runtime): resolve flow-control stream state once per lifecycle - #742
SunSi12138 wants to merge 90 commits into
Conversation
…treamDispatcher.cs
…oledAsyncStreamDispatcher.cs
…eAdmissionStreamDispatcher.cs
…cSession.PreCreditStreaming.cs
…reamFlowController.cs
…s/ResolvedFlowStateEvidenceRunner.cs
…/Runtime/StreamFlowControllerTests.ResolvedStateLease.cs
d00cf63 to
32f1f55
Compare
Evidence result on latest
|
Keep receive callbacks, captured generations and route keys alive until every acquired DATA dispatch releases, including the synchronous failed-request cleanup path. Complete mailboxes immediately but defer final receive terminal/cleanup through a single cold-path drain continuation. Preserve immediate logical detach while an atomic cleanup pin prevents pooled-dispatcher reuse before terminal credit publication. Keep final release outside dispatch exception handling so cleanup failures cannot double-release acquisitions. Bind dispatcher ownership before callback mutation or receive-state resolution. Reject an already-bound pooled dispatcher without attaching ownerless flow state or erasing the original route callback; rollback any captured unpublished generation if later route insertion fails. Add 30 deterministic tests for before/after debit, plain/compressed PreAdmission DATA, stream 0/nonzero, request/stream/unregister completion, binding rollback, release-before-continuation installation, cleanup exceptions and detached-pool pinning. The first 29 controls fail against the original runtime; final default and disposable experimental UnitTests each pass 1961/1961, zero skipped. Ready-writer self-check passes 171/171. Release builds have zero warnings/errors; formatting, original maintainability and reference-boundary checks pass. Uploaded tree matches the locally validated sources. Performance acceptance remains BLOCKED: integrated 885306c evidence has NativeAOT short-stream -11.28% and Server1x16 allocation increases. Document the exact artifact and independently measured +48 B/route footprint instead of claiming Go from integrity CI. Local allocation gate has 3/4 passing cases; c1 median is under budget but spread 66.92 exceeds 50 B/op (baseline control passes). NativeAOT local publish is not validated because the offline runtime pack is unavailable. Preserve failures; require fresh CI. No workflow, timeout, population or budget is relaxed. Keep #735 open and #742 Draft.
|
Submitted Performance acceptance remains blocked; this PR remains Draft. The integrated candidate's NativeAOT short-stream -11.28% ns/item improvement and Server1x16 +73.44/+54.24 B/item are retained. A separate 3-repeat route-lifecycle allocation probe confirms a fixed +48 B/route contribution. Correctness fixes and successful evidence collection do not remove these costs. No workflow, threshold, timeout or population was weakened in this increment. Full fix, two-round self-check and CI/evidence record. The prior Ready/Go conclusion has been withdrawn in the PR body and acceptance document. Production Phase A #73 was still collecting E2E at the last check and is not reported as complete. |
…wnership Move terminal-published, peer-terminal and retirement-claimed flags into disjoint spare bits of the existing DispatcherEntry atomic state word. Keep the original acquisition count/limit, Close/Detach, cleanup pin, captured receive lease and all retirement ordering intact. No new per-item synchronization, pooled entry, callback indirection or state map. Pre-submit validation ran remotely on a separate disposable preflight checkout because the local executor was unavailable; no uncompiled runtime was pushed to PR 742. Run 37331620087 built and measured unchanged 6ca43ee first, then applied this exact source transformation. Three 10,000-lifecycle repeats: stream0 256/256/256 -> 240/240/240 B/route; stream7 392/392/392 -> 376/376/376. A real 16 B/route reduction in every repeat. Both review rounds passed: zero-warning/error Release builds, changed-file formatting, original maintainability/reference gates; focused checks 11/11 on control and candidate, complete default and experimental UnitTests each 1972/1972 with zero skips, actual JIT/NativeAOT writer self-checks 171/171. Retain the first preflight shallow-checkout setup failure separately. Promote only runtime change, permanent tests and evidence documentation; no preflight workflow or existing gate modifications. This is a partial allocation optimization, not production Go. Short-stream E2E allocation, NativeAOT latency and contention still need new comparable evidence. Keep #735 open and #742 Draft.
Keep default stream0 in its existing inline slot and materialize the nonzero route dictionary only when a named stream is published under the existing registry lock. Missing named-route operations do not allocate storage. Preserve mixed-route identities, locks, complete receive leases, acquired-DATA retirement and all bind/terminal rollback rules. Pre-submit run 37335422646 built unchanged 2a649a9, proved the intended eager-map regression, then applied the exact candidate blob in a disposable remote checkout. Three 10,000-lifecycle repeats show stream0 240/240/240 -> 160/160/160 B/route; stream7 stays 376/376/376. Combined with the preceding flag change, the chained default-only control is 256 -> 240 -> 160 B/route. This is allocation attribution, not RPC throughput or NativeAOT performance acceptance. Both review rounds passed before advancing the original PR: zero-warning/error builds, original formatting/maintainability/reference gates, six new dictionary tests, eleven retained flag/allocation tests, complete default and experimental UnitTests each 1978/1978 with zero skips, and actual JIT/NativeAOT writer checks 171/171. Source diff hash matches runtime blob a8fa8e8. Keep preflight scripts/workflow off the PR. No existing performance gate, test population, protocol, window or pool policy is relaxed. Production short-flow allocation/latency and connection contention require fresh comparable evidence. Keep #735 open and #742 Draft.
|
Submitted two preflight-validated storage optimizations on this existing PR: The chained allocation controls are default-only route 256 -> 240 -> 160 B/lifecycle and named route 392 -> 376 -> 376 B/lifecycle, each value reproduced in all three 10,000-lifecycle repeats of its matched control/candidate run. The latest pre-submit complete default/experimental suites each passed 1978/1978, zero skipped, and actual JIT/NativeAOT writer checks 171/171. The intended eager-map structural regression was first observed on the unchanged control. Existing receive-credit/ABA/bind-rollback/retention regressions and ordinary CI gates remain intact. Detailed implementation, two review rounds, artifact identities and evidence boundaries. Still Draft. These are per-lifecycle allocation controls, not new production RPC B/item or throughput results and not a fix for the controller's NativeAOT short-stream initialization overhead. Current-head correctness and NativeAOT evidence jobs have passed; complete production/performance jobs are tracked separately. No previous Ready/Go claim is restored by these partial wins. |
Source-only snapshot of the candidate tested in preflight 37403642475. Production blobs exactly match that disposable build: StreamManager 699636a and Routing 6892964. Full default and experimental tests pass 1987/1987 and actual JIT/NativeAOT writer controls pass 171/171. Lifecycle allocation falls 16 B for both default and named routes with and without receive callbacks. Do not promote this candidate to #742: the retained 24-process RPC control shows Server100x16 throughput -6.01% TCP and -8.60% SharedMemory with allocation medians increasing +4.98/+2.30 B/item, despite short-flow allocation improving. This snapshot preserves the failed performance candidate for code-generation attribution; workflow success is not acceptance. No existing PR head, test gate, timeout or workload is changed.
Retain the failed unhinted compact source as a separate ancestor/control, not as a PR update. In the disposable candidate only, add an AggressiveInlining hint to the full-lease reconstruction boundary. Capture optimized dispatch code in separate diagnostic processes for unchanged e834, unhinted compact, and the new inline candidate. Keep the same 24 uninstrumented real-RPC controls, report every launch's allocation and throughput plus CPU medians, and rerun the two engineering/correctness review rounds. The source transform is blob-pinned; all original gates, timeouts, populations, windows and pool rules stay unchanged. Source-only preflight changes remain off #742. No acceptance is claimed from CI success.
|
Continued performance work without promoting regressing candidates. The PR remains The current production evidence now shows lower Server1x16 allocation versus pinned dev (TCP -18.91 B/item, SharedMemory -44.75), but NativeAOT short-flow attribution still regresses -7.36% and PR Fast's c1 allocation spread is 51.576 > 50 B/op. Neither is waived. Two independently validated compact-route variants each saved another 16 B/lifecycle and passed complete default/experimental tests plus JIT/NativeAOT writer correctness. Their fixed actual-RPC controls did not jointly pass throughput/allocation acceptance, so neither was pushed to this PR. A third isolated prototype fuses first receive-state resolution, credit debit and generation capture under one controller gate. Actual NativeAOT single-item lifecycle measurements improved from 108.05 to 89.51 ns/item versus separate resolve/accept (+17.16% time improvement), and from 94.48 to 89.51 versus keyed (+5.26%). The 32-active-stream NativeAOT control also improves. PGO ON with one active stream is still 8.16% slower than keyed; it remains a negative control. Full default UnitTests 1987/1987, 9 new contracts in JIT and NativeAOT, a two-failure deliberate negative variant, and all 432 predefined mechanism rows have been verified in preflight 37406519822. This is warmed-controller candidate-internal attribution, not production RPC integration, cold-route allocation or a contention/Go verdict. Production adoption still needs correct first-frame/callback publication and all previously fixed lifecycle barriers. No original gates, timeouts, windows or populations changed. Full experiment identities, all outcomes, raw artifacts and remaining integration boundary. |
…motion Keep #742 at e834d3c. In disposable checkouts only, apply the exact locally compiled seven-file candidate for first-DATA resolve/debit plus route callback publication. Direct consumption-aware routes defer first receive state; retained PreAdmission mailboxes keep their existing eager contract. Acquired frames pin initialization, the captured generation and deferred retirement. Concurrent first frames wait for callback and first-delivery publication; failed undelivered initialization refunds only the winner's debit. Empty deferred routes cannot complete another generation by key. Local focused controls pass 25/25, including actual RpcSession/WindowUpdate and two deliberate two-failure mutation groups. An earlier full run passed 2003/2003; final exact-tree revalidation is 2002/2003 with the existing reconnect-policy timer-wait test timing out, retained rather than replaced. Original engineering gates and zero-warning builds pass. The code and test patch SHA256 is 111f6a122b9481f732e319c42ab9f5d6aefddf6b0a845e26cd22b0b9a7440279; multipart transport is checked and expanded to a plain reviewable patch before compilation. Do not promote: the local fixed 24-process RPC screen shows TCP Server1x16 -12.00% throughput / +14.44% CPU despite lower allocation and positive 100-item medians. A same-binary eager/fused control also retains a short TCP regression. These are negative incremental controls, not Go evidence. Run independent complete default/experimental correctness, actual generated NativeAOT TCP/SharedMemory smoke, and fixed 24-process RPC screens for each PGO setting. All failures, source hashes and individual reports are retained; workflow success establishes integrity only. No original PR workflow, allocation threshold, socket profile, timeout, population or production default is changed.
… smoke Keep the exact single-await runtime blobs validated by 37434398376. Prepare one identical minimal host for e834d3c and the disposable candidate, retaining the original benchmark service, contracts, transport environment and measured loop. Adapt only result JSON outside the measured interval to source-generated metadata; record every source/harness hash and both native binary identities. Publish and execute actual NativeAOT binaries, requiring RuntimeFeature.IsDynamicCodeSupported=false. Measure the same short/100-item TCP/SharedMemory server-stream controls in 24 predefined AB/BA/AB processes. Retain all latency, throughput, CPU, allocation and failed outcomes. This is incremental real native RPC evidence, not the full pinned-dev acceptance matrix. The original #742 and its gates remain unchanged and Draft.
|
Continued first-receive integration work on the existing preflight branch; the original PR remains The source-pinned integration is recoverable. New candidate The same runtime completed all 48 fixed JIT RPC processes and, through a minimal identical generated-RPC host on both revisions, 24 actual NativeAOT RPC timing processes. Native timing is now measured rather than inferred from AOT smoke. Runtime/harness hashes, native binary identities, raw reports and negative outcomes are retained. Do not promote this candidate yet. JIT PGO ON SharedMemory Server100x16 is -1.62% throughput / +4.05 B/item, with all three allocation repetitions increasing; PGO OFF is -3.62% / +4.54 B/item. Native short-flow throughput remains slightly negative (TCP -1.15%, SHM -0.70%), and native SHM allocation medians increase +3.48 B/item short / +0.34 long. These incremental screens compare against e834, not pinned dev, and do not replace the full issue acceptance matrix. Collection success is not Go. Complete source identities, two-round checks, all JIT/native results, failed tooling builds and artifacts. No original workflow, threshold, timeout, window or population was weakened. |
Keep the validated single-await runtime unchanged and instrument only both identical benchmark harnesses with two EventSource boundary markers. Pin dotnet-trace 10.0.745401 and TraceEvent 3.2.8; first calibrate inside/outside-window filtering with known allocation types and require no event loss. Collect 12 fixed allocation-sampling processes: SharedMemory/TCP Server100x16, control e834 versus the exact single-await candidate, three AB/BA/AB repeats. Preserve raw traces, per-process measurements, object-size samples and type-estimate deltas, including every negative outcome. AllocationTick attribution is sampled diagnostic evidence, not exact type counts or a profiled throughput Go decision. No new runtime optimization is promoted to #742, no production gate is weakened, and no benchmark acceptance population is replaced. The purpose is to identify actual allocating state machines/objects before changing more concurrency code.
The latest 0bcc candidate reduces allocation in every screened cell but retains PGO-ON long-flow throughput negatives. Do not conflate that with the cost of either independent change. Reconstruct the verified full candidate, then restore all first-receive/route/controller integration files to published e834 while keeping exactly the pooled SlowMoveNext builder, two single-consumption client wrapper fixes, and their 18 controls. The five-file isolated candidate builds locally with zero warnings/errors; focused controls pass 18/18 and full default UnitTests pass 1996/1996, zero skipped. Local offline restores disable NuGet audit only on the invocation; CI retains original policies. This temporary preflight requires both original-wrapper and original-builder negative controls, original engineering gates and full default/experimental suites again. Measure published e834, the exact previously validated fused+pooled candidate, and wait-only isolation on the same fixed three-arm 108-process JIT PGO OFF/ON and actual NativeAOT RPC population. Report all pairwise timing, CPU, allocation and p99 values without retries, removed cells, changed socket/windows or altered acceptance gates. Keep #742 unchanged and Draft pending evidence.
Build on fixed PR #742 head e834d3c. Add the existing three-file handoff candidate and 14 real-SendPump regression cases. Keep ordinary/progress budgets, timed flush policy, bounded ordinary/ready selection and buffer ownership through flush and stop. This is the handoff layer only, not a completed B3 RPC integration or a performance Go claim. No workflow, test population, timeout, allocation threshold or production flow-control default is relaxed. CI has not yet run for this tree.
Port just #742's validated lazy nonzero route storage mechanism onto current unmodified dev. Stream 0 keeps its existing inline slot and compare-exchange admission; a missing named route does not allocate storage; the map is created under the existing per-request registry gate only upon first successful named publication. Preserve all route-key semantics, active counts, dispatcher lifetime, and original flow control. Add six focused actual StreamManager test cases for default-only register/unregister, missing named dispatch/peer completion, mixed named/default routes, connection completion and concurrent registration. This is not the resolved-lease rewrite, packed-flags experiment or B3 scheduler. The prior #742 adjacent probe attributed -80 B/default-only route on its own measured head; independent current-dev allocation and package gates are required before claiming identical deployment savings.
Post-B3 salvage triage — keep #742 Draft, move proven independent changes outAt maintainer request, the two B3-only WIP PRs #800 and #803 have been closed without merge. #803's genuine generated-RPC JIT loss and repeatable cancellation stress failures remain archived; do not claim its historically positive B3 research evidence is a production improvement. #742 itself remains open Draft and should not be merged wholesale. Current standalone dev base is
Additional proven mechanism in #742, not blindly cherry-pickable: packing three cold lifecycle flags into spare bits of the existing long entry state word reduced 16 B/route in the #742 preflight (run 37331620087), with full correctness/JIT/NativeAOT functional checks. However #742's Do not salvage as production optimizations without fresh evidence: resolved-state Phase A (mixed E2E, contention/short-flow regression), B3 writer-owned integration (No-Go and closed), first-DATA fused resolve/debit (tombstone-capacity correctness change), retirement OR fusion (model-only, C# not verified), and separate route-lock-object removal (mechanism-only/local measurements, no accepted E2E improvement). The original #742 receive-lease lifetime/bind rollback fixes are primarily correctness for its new resolved-leasing model; do not assume the original dev has those same failure modes or transplant them unconditionally. The independent dev correctness bug above is tracked in #840. No original PR, dev production branch, runtime defaults, acceptance thresholds or protocol changes were merged by this triage. |
…equests (#841) * perf(runtime): allocate named stream route dictionary only when needed Port just #742's validated lazy nonzero route storage mechanism onto current unmodified dev. Stream 0 keeps its existing inline slot and compare-exchange admission; a missing named route does not allocate storage; the map is created under the existing per-request registry gate only upon first successful named publication. Preserve all route-key semantics, active counts, dispatcher lifetime, and original flow control. Add six focused actual StreamManager test cases for default-only register/unregister, missing named dispatch/peer completion, mixed named/default routes, connection completion and concurrent registration. This is not the resolved-lease rewrite, packed-flags experiment or B3 scheduler. The prior #742 adjacent probe attributed -80 B/default-only route on its own measured head; independent current-dev allocation and package gates are required before claiming identical deployment savings. * fix(runtime): treat missing lazy named routes as absent in terminal-discard cleanup Current-head PR Fast and Package Smoke on b3af181 fail before tests (CS8602) because RequestDispatchers is a partial class also used by StreamManager.TerminalDrain.cs. Take the named-map reference under the existing per-request lock; return false when the map has never been materialized. This is the same missing-named-route invariant as the earlier lazy storage change. Preserve terminal removal and route identity. No original test, gate, workflow or quota is relaxed. * test(runtime): measure standalone lazy named-route allocation against pinned dev PR Fast and Package Smoke 38157502795 / 38157502775 passed on the isolated route-map port. Add an opt-in UnitTests friend-assembly allocation probe that reuses one stateless dispatcher and measures three warmed 10,000-register/unregister lifecycles for default and named routes. The additive workflow copies exactly the same probe source into frozen dev f0fee51 and builds both binaries on one runner, alternating dev-A/candidate/dev-B for 4 rounds, preserving 12 raw process results and A/A controls. The regular tests, performance thresholds, product paths, windows and protocols are unchanged; these numbers attribute per-route allocations only, not RPC QPS. * test(runtime): use identical camel-case evidence JSON across both measured binaries The additive route-allocation workflow parser checks stable camel-case provenance fields. Make the shared UnitTests probe explicitly serialize those names rather than relying on the serializer's default Pascal-case anonymous-property names. This affects only the diagnostic artifact format; regular UnitTests, route implementation, allocation thresholds and source comparisons are unchanged.
|
Closing this superseded #735 research Draft without merge. The two measured footprint reductions and their evidence remain preserved in this PR/branch, but production RPC throughput, NativeAOT latency, and contention Go gates were not established. The later consolidated architecture audit and No-Go decision are tracked in #852, with follow-up tracked by #735. This closure is not a claim that the underlying optimization is invalid; it means this particular candidate is not a production merge vehicle. No branch or evidence artifacts are deleted. |
Refs #735
Status: Draft — two validated footprint reductions, production acceptance not yet passed
Current head:
e834d3c28c87ad496989af925515cf21babd308d.Current tree:
4afb01297ffe8af9b9e27dfcae6663403aaa2c60.This head adds lazy named-route storage to
2a649a9880589696448e21ce0bd2e67ffd174147(packed lifecycle flags). Both follow6ca43ee8e434f2796a9e8d65f49d777d36f52fd2, including dev0fe26024b114bb6e78411a9b86276086c045d03d.Production performance acceptance remains blocked. These changes have real allocation-probe results and correctness validation. They do not, by themselves, establish production RPC B/item, NativeAOT short-stream latency or contention acceptance. Do not equate successful collection workflows with #735's joint Go requirements. Keep the issue open and this PR Draft.
Changes in this optimization round
The complete receive lease still belongs independently to the route. No entry pool, second state map, smaller negotiated capacity, callback lookup, protocol change or new per-item synchronization was introduced. Previously fixed acquired-DATA credit lifetime, same-key generation, bind rollback and pooled-reference retention rules remain intact.
Relative to 6ca43ee there are two commits and five changed files: one production routing file, two test files and two evidence documents. Existing workflows, deadlines, populations, allocation budgets and acceptance thresholds are unchanged. Temporary preflight workflows/scripts were not promoted into this PR.
Measured allocation — attribution, not E2E
Same probe at each step: one reused stateless dispatcher, no flow callbacks, 2,048 warmups, three repeats of 10,000 Register/Unregister lifecycles. Each adjacent control/candidate comparison ran on the same Linux x64 runner, measuring allocations only around the loop.
The lazy-map change alone saves 80 B/default-only request and adds no allocation to the named-route control. It does not claim that saving for mixed/nonzero requests. The chain comes from two separately retained adjacent comparisons, not a single three-revision timing benchmark.
Do not subtract these values from old RPC measurements to claim a new E2E B/item result. NativeAOT publication below establishes correctness, not a native performance improvement. No microkernel short-flow benefit is claimed: these changes do not alter the controller's separate resolve/debit sequence.
Two self-check rounds before each original-PR submission
Local execution was unavailable, so actual validation ran first on the existing temporary preflight branch with read-only Actions permissions. It verified unchanged shipping sources, built/measured the fixed control, applied a source-blob-pinned candidate only in its disposable checkout and reran checks before this PR was advanced.
First reduction: compact flags
Run 37331620087, artifact
11355220166.Actions-reported SHA256:
6108ec4ee955ef185769fbc4c4f90f45b7e07a3e0fa23382296fc3de64898074.Build/engineering: zero warning/error Release builds, changed-file formatting and original maintainability/reference boundaries pass.
Contracts: 11/11 focused cases on control and candidate; complete default and experimental suites each 1972/1972, zero skips; actual JIT and NativeAOT writer self-checks 171/171.
The initial preflight shallow-checkout setup failure is retained; it occurred before compilation. Only history/ancestry validation was repaired, not runtime/tests/measurement thresholds.
Second reduction: lazy named-route map
Run 37335422646, attempt 1, job
111848850430, artifact11355583391with 29 evidence files.Actions-reported SHA256:
5f546e0994b85e4997e76b48513dd69f98f9a49a31110402cb0d4156b31ced63.Runtime routing blob:
a8fa8e890ceaf341a552651fc289c3bddc0b1c4a.Permanent test blob:
2d06e535fcc4a6b355ed6480179db72ba03f5418.Build/engineering: zero warning/error builds, formatting and original maintenance/reference gates pass.
Contracts: the intended default-route eager-allocation test fails on unchanged 2a649a9, then 6/6 new cases pass on the lazy candidate; retained flags/allocation 11/11. Full default and experimental suites each 1978/1978, zero skips. Actual JIT and NativeAOT writer self-checks 171/171. Existing evidence-guard Python suites also pass.
The six tests cover absent storage, default/named replacement, missing-named operations, default-only and mixed connection teardown, and concurrent default/nonzero registration. All earlier receive-credit/ABA/rollback/pool-retention regressions remain in the full suites.
Retained correctness fixes
An acquired DATA dispatch pins its receive callback, captured generation and route key through the last release, including synchronous failed-request cleanup and pre-debit/post-debit interleavings. Deferred terminal/cleanup and the existing cleanup pin prevent premature dispatcher reuse while preserving required logical detach. Cleanup failures cannot release an acquisition twice.
Binding is validated before callback mutation/receive-state resolution. Failed rebinding cannot attach ownerless flow state or erase an old route's callback; failed insertion rolls back only the captured unpublished generation. These paths were not changed by the two storage optimizations.
Performance interpretation and remaining blockers
Microkernel: candidate-internal keyed vs resolved ns/item attribution.
Production E2E: pinned dev vs candidate binaries.
B3: isolated writer-ownership research, not the production candidate's E2E result.
Historical integrated 885306c evidence (run
37190672744, artifact11299511677) showed NativeAOT short-flow ns/item improvement -11.28%, TCP Server1x16 allocation +73.44 B/item, SHM +54.24 B/item, with all three repeats increasing allocation. These were genuine blockers, not overridden by old B3 gains.Completed 6ca43ee evidence (run
37222858782) also showed short-flow problems: NativeAOT short-flow cost +15.69% vs keyed; TCP Server1x16 -7.51% throughput / +51.07 B/item, SHM -2.98% / +52.77 B/item. These are historical measurements, not claimed measurements of e834d3c.The new combined head requires its own production E2E/allocation and native timing results. Compact lease metadata, first-DATA resolve/debit overhead and shared connection contention remain separate follow-up work; this round does not declare them fixed.
Current-head CI
New-head runs have started: PR Fast
37336638809, Package Smoke37336639012, Ready Writer37336639017, production resolved-state evidence37336638940. Running jobs are not counted as passed. The independent pre-submit successes above are not presented as the final head's completed CI. Subsequent comments record actual conclusions, including non-gating diagnostic failures and any missing timing population.Evidence documents:
doc/performance/flow-state-route-flags.mddoc/performance/flow-state-lazy-route-map.mddoc/performance/flow-state-735-integrated-review.mddoc/performance/flow-state-735-acceptance.md