Repository navigation
perf: plugin gate install — children index for the in-memory store; SLOW_DISPATCH at a real 500 ms - #4169
Merged
Conversation
…emory store, and SLOW_DISPATCH at a real 500 ms Measured 2026-09-13 on Plugins run 34731952463 (Gate shard 1/1, 26 min): 1.3 min bake, 18.3 min INSTALLING 63 packages into the disposable mesh, 3.6 min compile+render+tests. A dotnet-trace of one package locally (Hosting, 198 nodes): 12.5 % of samples in InMemoryStorageAdapter.ListChildPaths — a full scan of every key per call, one call per directory level of every subtree query the installer issues per package, so quadratic in the mesh; and the log flood: SlowDispatchTicks was 100-ns ticks compared against Stopwatch ticks, i.e. 5 ms on Linux — 16,000 SLOW_DISPATCH lines per shard at Information (366 per package). The index maps a directory to its immediate children, keyed by the dictionary instance so adapters sharing one store share one index; pinned by InMemoryStorageAdapterChildIndexTest. The threshold is now Stopwatch.Frequency / 2. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DqTDZe4Skkn81GuGkwMrXS
…ped by ANOTHER package The dance exists for a root whose NodeType is defined in the package being installed; every non-static root took it. On the plugin gate that is every Store/Plugin satellite (Hosting, Signature, Essentials, …): one placeholder write, one retype, one hub recycle per package, and behind the recycle a batch of [UpdateQueue] ADVANCE_WITHOUT_HANDOFF bound=5000ms waits on the package's compile-state writes — 13 s per package with NodeTypes (Plugins run 34731952463). Maintainer, 2026-09-13: "must be done on running mesh not ramp up and down". Graph tests (19 install/placeholder/retype cases) green. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DqTDZe4Skkn81GuGkwMrXS
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
…k bridge (ObservableToTaskBridgeGuard)
rbuergi
added this pull request to the merge queue
Sep 13, 2026
This was referenced Sep 13, 2026
Merged
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.
Where the gate's time goes (measured 2026-09-13, Plugins run 34731952463,
Gate shard 1/1, 26 min)compile /repo, 1,100 nodes / 63 packages, no mesh)A dotnet-trace (EventPipe sampling) of one package locally (Hosting, 198 nodes) puts 12.5 % of the samples in
InMemoryStorageAdapter.ListChildPaths— a full scan of every key of the store per call, called once per directory level of every subtree query the installer issues per package: quadratic in the mesh, and the part that scaled 4× from a laptop to a 2-vCPU runner. Fix: a children index (directory → immediate child nodes + implied directories), maintained by every write path, keyed by the dictionary instance (shared stores share one index), rebuilt once if a test seeds the dictionary directly. Pinned byInMemoryStorageAdapterChildIndexTest; the 37 Hosting tests touching the adapter and subtree queries pass.Second finding:
SlowDispatchTicks = TimeSpan.TicksPerMillisecond * 500(100-ns ticks) is compared againstStopwatch.GetTimestamp()deltas — on Linux that is 5 ms, so every dispatch over 5 ms loggedMESSAGE_FLOW: SLOW_DISPATCHat Information: 366 lines per package install, 16,000 per shard (the gate raisesMeshWeaver.Messaging.MessageHubto Information for QUIESCE attribution). NowStopwatch.Frequency / 2— the 500 ms the comment always described, on every platform. Production instances stop emitting that flood too.Second commit — no ramp-up/down for foreign-typed roots. The installer did the placeholder → retype → root-recycle dance for EVERY non-static root; it is only needed when the root's NodeType is defined in the package itself. Every
Store/Pluginsatellite (nearly all of Plugins) now writes its root with its final type once and recycles nothing — which is where theADVANCE_WITHOUT_HANDOFF bound=5000msbatches (13 s per package with NodeTypes) came from. Graph install/placeholder/retype tests (19) green.Still next, measured: the sequential prebuilt-assembly adoption (1.5 s per type on CI). Note for readers of red gates meanwhile: on
ubuntu-latestan UNSHARDED gate is cut at the 30-min cap by install time alone (Plugins#1764 run 34747207818); the 4-shard gate (#1771) and this PR are the fix, not the cap.🤖 Generated with Claude Code
https://claude.ai/code/session_01DqTDZe4Skkn81GuGkwMrXS