Repository navigation
[Vsintegration] Fix slow solution close in the code model - #2124
Merged
RobertvanderHulst merged 1 commit intoOct 26, 2026
Merged
RobertvanderHulst merged 1 commit into
RobertvanderHulst merged 1 commit into
Conversation
XSolution.Close() closed every project through XProject.Close(), which called XSolution.Remove(). That removed the project from the references of every other project in the solution, and each removed assembly reference called SaveAssemblyReferencesToDatabase(). That method read the AssemblyReferences property, which calls ResolveReferences() and can re-read referenced assemblies from disk, while the database was already closed. In large solutions this blocked the UI thread for minutes: classic projects stayed at "0 of x projects" in the close dialog, SDK projects hung after the solution was closed. - XSolution.Close() now empties the project list before closing the projects, so XSolution.Remove() returns at once. Unloading or removing a single project still cleans up the references as before. - SaveAssemblyReferencesToDatabase() passes the _AssemblyReferences field and no longer triggers ResolveReferences(). Measured in the VS 2022 experimental instance: RadixWf.sln (98 projects) spends 2.1 s in the code model on close, RadixWfSDK.slnx 3.8 s, nearly all of it saving the database. Before, closing took between seconds and more than 3 minutes (RadixWfSDK.slnx), and up to 17 minutes (RadixWf.sln). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
Great catch. This really makes a difference! |
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.
Summary
Closing a large solution blocked the UI thread for minutes. Classic projects stayed at "0 of x projects" in the close dialog; SDK projects hung after "Closed solution".
XSolution.Close()closed each project, and every close removed that project from the references of all other projects. Each removed reference saved the reference list through theAssemblyReferencesproperty, which runsResolveReferences()and re-reads assemblies from disk. The database was already closed at that point, so all of this work was thrown away.SaveAssemblyReferencesToDatabase()now passes the_AssemblyReferencesfield, so saving never triggers reference resolution.Unloading or removing a single project still goes through
XSolution.Remove()with the full reference cleanup.Evidence
Intellisense log, time the code model needs on solution close:
XSolution.Close()ran for more than 3 minutes after "Closed solution", with 26,000+ "Database is not open" calls on the UI thread. RadixWf.sln (98 classic projects, X# 3.0.x): 1–10 s normally, 13 and 17 minutes in two sessions.After (this branch, VS 2022 experimental instance, both solutions closed 1–2 minutes after loading): RadixWfSDK.slnx 3.8 s, RadixWf.sln 2.1 s. In both, nearly all of that time is
SaveToDisk+VACUUMof the database; noXSolution.Remove()calls and no database access after the database was closed.Merge Danger
Door: two-way
Blast Radius: solution-close
Only the code path for closing the whole solution changes. Not addressed here: CPS background threads still resolve references while the database is being closed, which logs
InvalidOperationExceptionandNullReferenceExceptioninAssemblyReader.AddType. That race existed before this change and does not block the UI thread.🤖 Generated with Claude Code