Cache the MEF composition in the Roslyn LSP.#76276
Conversation
312cd6b to
6b38161
Compare
6b38161 to
2e9a0e7
Compare
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Outdated
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Outdated
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Show resolved
Hide resolved
| { | ||
| // Include the .NET runtime version in the cache path so that running on a newer | ||
| // runtime causes the cache to be rebuilt. | ||
| var cacheSubdirectory = $".NET {Environment.Version.Major}"; |
There was a problem hiding this comment.
Does that Version.Major mean a minor update won't create a new cache? Is that a problem?
There was a problem hiding this comment.
I am not 100% sure. I took this bit from DevKit and have updated the comment to match theirs. I know we have changed target runtime from 8.0.9 to 8.0.10 and now 8.0.11 seemingly without incident.
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Outdated
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Outdated
Show resolved
Hide resolved
...r/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs
Outdated
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Outdated
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Show resolved
Hide resolved
dibarbet
left a comment
There was a problem hiding this comment.
generally looks good - assuming the telemetry is fixed/removed and the async call to save the cache is tracked
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Outdated
Show resolved
Hide resolved
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs
Outdated
Show resolved
Hide resolved
| { | ||
| await using var testServer = await CreateLanguageServerAsync(includeDevKitComponents: false); | ||
|
|
||
| var mefCompositions = Directory.EnumerateFiles(MefCacheDirectory.Path, "*.mef-composition", SearchOption.AllDirectories); |
There was a problem hiding this comment.
ah, thanks. Will fix up.
There was a problem hiding this comment.
Out of curiosity, I thought the IAsynchronousOperationListener was the way that we usually exposed async operations to tests. Was that not an option?
There was a problem hiding this comment.
I will admit I have not tested a lot of these async operations. Looking through the source it seems the IAsynchronousOperationListenerProvider is typically MEF imported but this code is building the MEF composition, so we couldn't follow that pattern. Nothing is stopping us from creating our own listener instance and making it available through the TestAccessor, but I am not sure that has any benefits over using a Task. If you know of any reasons, I am happy to rework this bit in a follow up.
| var typeRefResolver = new ExtensionTypeRefResolver(assemblyLoader, loggerFactory); | ||
|
|
||
| using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(extensionManager, assemblyLoader, serverConfiguration.DevKitDependencyPath, loggerFactory); | ||
| var cacheDirectory = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location)!, "cache"); |

To improve startup time of the LSP we can cache the MEF composition and load it from file instead of building up a new composition.
The cache is invalidated when:
dotnet.server.pathis updated).Resolves #68568