Coalesce the assembly tree's selection and removal fan-out - #4157
Open
siegfriedpammer wants to merge 2 commits into
Open
siegfriedpammer wants to merge 2 commits into
siegfriedpammer wants to merge 2 commits into
Conversation
siegfriedpammer
force-pushed
the
perf/tree-selection-fanout
branch
from
September 21, 2026 15:50
6b7b19c to
3535bb2
Compare
This was referenced Sep 21, 2026
Deleting assemblies one at a time is not equivalent to deleting them together: each removal raises its own collection change, and the listeners of the assembly list react to one of those by pruning navigation history, restarting a running search, re-querying every bound command and re-decompiling whatever is still selected. Selecting an expanded list and pressing Delete therefore paid for all of that once per assembly, and froze the UI. Emptying the list still reports a Remove rather than the Reset that Clear() raises, because consumers read Reset as "re-read everything" and several short-circuit their per-removal cleanup on it, which would leave tabs and navigation history pointing at unloaded assemblies. The tree's removal is reordered for the same reason: it detached and announced one node at a time, so a listener reacting to the first notification still found the rest of the same removal attached and took them for a selection the user had made. Assisted-by: Claude:claude-opus-5[1m]:Claude Code Assisted-by: OpenCode:openai/gpt-5.5:OpenCode
A selection change reaches a full application-wide command re-query, a session-settings write, a message-bus broadcast and a decompile of the new selection. The model already had a flag to hold that off during a bulk edit, but only its own SelectNodes ever set it: the binder that mirrors the tree's selection into the model added and removed one node at a time, so selecting every row cost one fan-out per row. The flag becomes a scope any bulk edit can enter, and the binder uses it. Membership now comes from a set rather than a scan of the model selection per node, which was quadratic once a large part of the tree was selected. DockWorkspace subscribed to both the selection collection and the SelectedItem property, so it showed the selection twice per change and once per node during a bulk edit; the property already fires when the selection settles, so the collection subscription goes. Assisted-by: Claude:claude-opus-5[1m]:Claude Code Assisted-by: OpenCode:openai/gpt-5.5:OpenCode
siegfriedpammer
force-pushed
the
perf/tree-selection-fanout
branch
from
September 21, 2026 15:51
3535bb2 to
9fb1a5a
Compare
This branch has not been deployed
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.
Selecting or deleting a large part of the assembly tree paid the cost of selection/list-change fan-out once per row.
This keeps the PR focused on the two highest-impact parts:
Removing a set of assemblies now happens in one logical list change. Deleting assemblies one at a time raised one collection change per row, and listeners reacted by pruning navigation history, restarting searches, re-querying commands and updating tabs once per event. The list now removes contiguous runs as ranged
Removenotifications so consumers still receive the removed items and indices without aReset.Selection fan-out is coalesced. The tree selection binder now mirrors bulk selection changes into the model inside a selection batch. Membership checks use sets instead of scanning the model selection per node, and
DockWorkspaceno longer subscribes to bothSelectedItems.CollectionChangedandSelectedItemfor the same work.The generic
BatchedObservableCollection<T>helper was removed; the assembly list now owns the small range-remove operation it needs locally.Verification
OPENSSL_ENABLE_SHA1_SIGNATURES=1 dotnet test --project ILSpy.Tests/ILSpy.Tests.csproj --filter SelectAllDeleteBatchingTests --report-trx: 2 passed.This PR description was written by an AI agent (OpenCode gpt-5.5) working under @siegfriedpammer's direction.