Skip to content

Commit 5e99a9f

Browse files
authored
Use lazy initialization for members in CodeFixService (#78484)
Defer expensive member initialization in the CodeFixService constructor. The Roslyn speedometer test shows this ctor as taking ~28ms during first C# file open while on the main thread. Instead, we can make a couple members lazy and have them initialized when needed (which happens much later, if at all, and on a bg thread) See PR for detailed speedometer results.
1 parent c87e204 commit 5e99a9f

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

src/Features/Core/Portable/CodeFixes/Service/CodeFixService.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ namespace Microsoft.CodeAnalysis.CodeFixes;
4040
internal sealed partial class CodeFixService : ICodeFixService
4141
{
4242
private readonly ImmutableArray<Lazy<CodeFixProvider, CodeChangeProviderMetadata>> _fixers;
43-
private readonly ImmutableDictionary<string, ImmutableArray<Lazy<CodeFixProvider, CodeChangeProviderMetadata>>> _fixersPerLanguageMap;
43+
private readonly Lazy<ImmutableDictionary<string, ImmutableArray<Lazy<CodeFixProvider, CodeChangeProviderMetadata>>>> _fixersPerLanguageMap;
4444

4545
private readonly ConditionalWeakTable<IReadOnlyList<AnalyzerReference>, ImmutableDictionary<DiagnosticId, ImmutableArray<CodeFixProvider>>> _projectFixersMap = new();
4646

4747
// Shared by project fixers and workspace fixers.
48-
private readonly ImmutableDictionary<LanguageKind, Lazy<ImmutableArray<IConfigurationFixProvider>>> _configurationProvidersMap;
48+
private readonly Lazy<ImmutableDictionary<LanguageKind, Lazy<ImmutableArray<IConfigurationFixProvider>>>> _configurationProvidersMap;
4949
private readonly ImmutableArray<Lazy<IErrorLoggerService>> _errorLoggers;
5050

5151
private ImmutableDictionary<LanguageKind, Lazy<ImmutableDictionary<DiagnosticId, ImmutableArray<CodeFixProvider>>>>? _lazyWorkspaceFixersMap;
@@ -65,9 +65,9 @@ public CodeFixService(
6565
_errorLoggers = [.. loggers];
6666

6767
_fixers = [.. fixers];
68-
_fixersPerLanguageMap = _fixers.ToPerLanguageMapWithMultipleLanguages();
68+
_fixersPerLanguageMap = new(() => _fixers.ToPerLanguageMapWithMultipleLanguages());
6969

70-
_configurationProvidersMap = GetConfigurationProvidersPerLanguageMap(configurationProviders);
70+
_configurationProvidersMap = new(() => GetConfigurationProvidersPerLanguageMap(configurationProviders));
7171
}
7272

7373
private Func<string, bool>? GetShouldIncludeDiagnosticPredicate(
@@ -455,7 +455,7 @@ private async IAsyncEnumerable<CodeFixCollection> StreamFixesAsync(
455455
var hasAnySharedFixer = TryGetWorkspaceFixersMap(document, out var fixerMap);
456456

457457
var projectFixersMap = GetProjectFixers(document);
458-
var hasAnyProjectFixer = projectFixersMap.Any();
458+
var hasAnyProjectFixer = !projectFixersMap.IsEmpty;
459459

460460
if (!hasAnySharedFixer && !hasAnyProjectFixer)
461461
yield break;
@@ -715,7 +715,7 @@ private async IAsyncEnumerable<CodeFixCollection> StreamConfigurationFixesAsync(
715715
{
716716
cancellationToken.ThrowIfCancellationRequested();
717717

718-
if (!_configurationProvidersMap.TryGetValue(document.Project.Language, out var lazyConfigurationProviders) ||
718+
if (!_configurationProvidersMap.Value.TryGetValue(document.Project.Language, out var lazyConfigurationProviders) ||
719719
lazyConfigurationProviders.Value == null)
720720
{
721721
yield break;
@@ -812,7 +812,7 @@ await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
812812
/// <summary> Looks explicitly for an <see cref="AbstractSuppressionCodeFixProvider"/>.</summary>
813813
public CodeFixProvider? GetSuppressionFixer(string language, IEnumerable<string> diagnosticIds)
814814
{
815-
if (!_configurationProvidersMap.TryGetValue(language, out var lazyConfigurationProviders) ||
815+
if (!_configurationProvidersMap.Value.TryGetValue(language, out var lazyConfigurationProviders) ||
816816
lazyConfigurationProviders.Value.IsDefault)
817817
{
818818
return null;
@@ -881,7 +881,7 @@ private ImmutableDictionary<LanguageKind, Lazy<ImmutableDictionary<DiagnosticId,
881881
{
882882
var fixerMap = ImmutableDictionary.Create<LanguageKind, Lazy<ImmutableDictionary<DiagnosticId, ImmutableArray<CodeFixProvider>>>>();
883883
var extensionManager = services.GetService<IExtensionManager>();
884-
foreach (var (diagnosticId, lazyFixers) in _fixersPerLanguageMap)
884+
foreach (var (diagnosticId, lazyFixers) in _fixersPerLanguageMap.Value)
885885
{
886886
var lazyMap = new Lazy<ImmutableDictionary<DiagnosticId, ImmutableArray<CodeFixProvider>>>(() =>
887887
{
@@ -942,7 +942,7 @@ static ImmutableArray<IConfigurationFixProvider> GetConfigurationFixProviders(Im
942942
private ImmutableDictionary<LanguageKind, Lazy<ImmutableDictionary<CodeFixProvider, int>>> GetFixerPriorityPerLanguageMap(SolutionServices services)
943943
{
944944
var languageMap = ImmutableDictionary.CreateBuilder<LanguageKind, Lazy<ImmutableDictionary<CodeFixProvider, int>>>();
945-
foreach (var (diagnosticId, lazyFixers) in _fixersPerLanguageMap)
945+
foreach (var (diagnosticId, lazyFixers) in _fixersPerLanguageMap.Value)
946946
{
947947
var lazyMap = new Lazy<ImmutableDictionary<CodeFixProvider, int>>(() =>
948948
{

0 commit comments

Comments
 (0)