未验证 提交 3fdf3c56 编写于 作者: M Manish Vasani 提交者: GitHub

Merge pull request #42605 from mavasani/SymbolStartPerf

Improve performance of analyzer driver in presence of symbol start an…
......@@ -63,7 +63,7 @@ internal abstract partial class AnalyzerDriver : IDisposable
/// 1. myActions: analyzer actions registered in the symbol start actions of containing namespace/type, which are to be executed for this symbol
/// 2. childActions: analyzer actions registered in this symbol's start actions, which are to be executed for member symbols.
/// </summary>
private ConcurrentDictionary<(ISymbol, DiagnosticAnalyzer), AnalyzerActions> _perSymbolAnalyzerActionsCache;
private ConcurrentDictionary<(INamespaceOrTypeSymbol, DiagnosticAnalyzer), AnalyzerActions> _perSymbolAnalyzerActionsCache;
private ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<ImmutableArray<SymbolAnalyzerAction>>> _symbolActionsByKind;
private ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<SemanticModelAnalyzerAction>> _semanticModelActionsMap;
......@@ -240,7 +240,7 @@ private void Initialize(AnalyzerExecutor analyzerExecutor, DiagnosticQueue diagn
if (this.AnalyzerActions.SymbolStartActionsCount > 0)
{
_perSymbolAnalyzerActionsCache = new ConcurrentDictionary<(ISymbol, DiagnosticAnalyzer), AnalyzerActions>();
_perSymbolAnalyzerActionsCache = new ConcurrentDictionary<(INamespaceOrTypeSymbol, DiagnosticAnalyzer), AnalyzerActions>();
}
}, cancellationToken);
......@@ -1288,7 +1288,10 @@ async Task onSymbolAndMembersProcessedAsync(ISymbol symbol, DiagnosticAnalyzer a
return;
}
_perSymbolAnalyzerActionsCache.TryRemove((symbol, analyzer), out _);
if (symbol is INamespaceOrTypeSymbol namespaceOrType)
{
_perSymbolAnalyzerActionsCache.TryRemove((namespaceOrType, analyzer), out _);
}
await processContainerOnMemberCompletedAsync(symbol.ContainingNamespace, symbol, analyzer).ConfigureAwait(false);
await processContainerOnMemberCompletedAsync(symbol.ContainingType, symbol, analyzer).ConfigureAwait(false);
......@@ -1811,6 +1814,11 @@ public bool HasSymbolStartedActions(AnalysisScope analysisScope)
var allActions = AnalyzerActions.Empty;
foreach (var analyzer in analysisScope.Analyzers)
{
if (!_symbolStartAnalyzers.Contains(analyzer))
{
continue;
}
var analyzerActions = await GetPerSymbolAnalyzerActionsAsync(symbol, analyzer, analysisStateOpt, cancellationToken).ConfigureAwait(false);
if (!analyzerActions.IsEmpty)
{
......@@ -1831,24 +1839,37 @@ public bool HasSymbolStartedActions(AnalysisScope analysisScope)
CancellationToken cancellationToken)
{
Debug.Assert(AnalyzerActions.SymbolStartActionsCount > 0);
Debug.Assert(_symbolStartAnalyzers.Contains(analyzer));
if (symbol.IsImplicitlyDeclared)
{
return AnalyzerActions.Empty;
}
if (_perSymbolAnalyzerActionsCache.TryGetValue((symbol, analyzer), out var actions))
// PERF: For containing symbols, we want to cache the computed actions.
// For member symbols, we do not want to cache as we will not reach this path again.
if (!(symbol is INamespaceOrTypeSymbol namespaceOrType))
{
return await getAllActionsAsync(this, symbol, analyzer, analysisStateOpt, cancellationToken).ConfigureAwait(false);
}
if (_perSymbolAnalyzerActionsCache.TryGetValue((namespaceOrType, analyzer), out var actions))
{
return actions;
}
// Compute additional inherited actions for this symbol by running the containing symbol's start actions.
AnalyzerActions inheritedActions = await getInheritedActionsAsync(this, symbol, analyzer, analysisStateOpt, cancellationToken).ConfigureAwait(false);
var allActions = await getAllActionsAsync(this, symbol, analyzer, analysisStateOpt, cancellationToken).ConfigureAwait(false);
return _perSymbolAnalyzerActionsCache.GetOrAdd((namespaceOrType, analyzer), allActions);
// Execute the symbol start actions for this symbol to compute additional actions for its members.
AnalyzerActions myActions = await getSymbolActionsCoreAsync(this, symbol, analyzer).ConfigureAwait(false);
AnalyzerActions allActions = !myActions.IsEmpty ? inheritedActions.Append(in myActions) : inheritedActions;
return _perSymbolAnalyzerActionsCache.GetOrAdd((symbol, analyzer), allActions);
static async ValueTask<AnalyzerActions> getAllActionsAsync(AnalyzerDriver driver, ISymbol symbol, DiagnosticAnalyzer analyzer, AnalysisState analysisStateOpt, CancellationToken cancellationToken)
{
// Compute additional inherited actions for this symbol by running the containing symbol's start actions.
AnalyzerActions inheritedActions = await getInheritedActionsAsync(driver, symbol, analyzer, analysisStateOpt, cancellationToken).ConfigureAwait(false);
// Execute the symbol start actions for this symbol to compute additional actions for its members.
AnalyzerActions myActions = await getSymbolActionsCoreAsync(driver, symbol, analyzer).ConfigureAwait(false);
return !myActions.IsEmpty ? inheritedActions.Append(in myActions) : inheritedActions;
}
static async ValueTask<AnalyzerActions> getInheritedActionsAsync(AnalyzerDriver driver, ISymbol symbol, DiagnosticAnalyzer analyzer, AnalysisState analysisStateOpt, CancellationToken cancellationToken)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册