未验证 提交 6f27d6d1 编写于 作者: S Sam Harwell 提交者: GitHub

Merge pull request #23637 from sharwell/rm-contention

Use ConcurrentDictionary to avoid locks in IsGeneratedCode and HasHiddenRegions
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
...@@ -77,7 +78,7 @@ internal abstract partial class AnalyzerDriver : IDisposable ...@@ -77,7 +78,7 @@ internal abstract partial class AnalyzerDriver : IDisposable
/// <summary> /// <summary>
/// Lazily populated dictionary indicating whether a source file is a generated code file or not - we populate it lazily to avoid realizing all syntax trees in the compilation upfront. /// Lazily populated dictionary indicating whether a source file is a generated code file or not - we populate it lazily to avoid realizing all syntax trees in the compilation upfront.
/// </summary> /// </summary>
private Dictionary<SyntaxTree, bool> _lazyGeneratedCodeFilesMap; private ConcurrentDictionary<SyntaxTree, bool> _lazyGeneratedCodeFilesMap;
/// <summary> /// <summary>
/// Lazily populated dictionary from tree to declared symbols with GeneratedCodeAttribute. /// Lazily populated dictionary from tree to declared symbols with GeneratedCodeAttribute.
...@@ -87,7 +88,7 @@ internal abstract partial class AnalyzerDriver : IDisposable ...@@ -87,7 +88,7 @@ internal abstract partial class AnalyzerDriver : IDisposable
/// <summary> /// <summary>
/// Lazily populated dictionary indicating whether a source file has any hidden regions - we populate it lazily to avoid realizing all syntax trees in the compilation upfront. /// Lazily populated dictionary indicating whether a source file has any hidden regions - we populate it lazily to avoid realizing all syntax trees in the compilation upfront.
/// </summary> /// </summary>
private Dictionary<SyntaxTree, bool> _lazyTreesWithHiddenRegionsMap; private ConcurrentDictionary<SyntaxTree, bool> _lazyTreesWithHiddenRegionsMap;
/// <summary> /// <summary>
/// Symbol for <see cref="System.CodeDom.Compiler.GeneratedCodeAttribute"/>. /// Symbol for <see cref="System.CodeDom.Compiler.GeneratedCodeAttribute"/>.
...@@ -163,9 +164,9 @@ private void Initialize(AnalyzerExecutor analyzerExecutor, DiagnosticQueue diagn ...@@ -163,9 +164,9 @@ private void Initialize(AnalyzerExecutor analyzerExecutor, DiagnosticQueue diagn
_generatedCodeAnalysisFlagsMap = await GetGeneratedCodeAnalysisFlagsAsync(unsuppressedAnalyzers, analyzerManager, analyzerExecutor).ConfigureAwait(false); _generatedCodeAnalysisFlagsMap = await GetGeneratedCodeAnalysisFlagsAsync(unsuppressedAnalyzers, analyzerManager, analyzerExecutor).ConfigureAwait(false);
_doNotAnalyzeGeneratedCode = ShouldSkipAnalysisOnGeneratedCode(unsuppressedAnalyzers); _doNotAnalyzeGeneratedCode = ShouldSkipAnalysisOnGeneratedCode(unsuppressedAnalyzers);
_treatAllCodeAsNonGeneratedCode = ShouldTreatAllCodeAsNonGeneratedCode(unsuppressedAnalyzers, _generatedCodeAnalysisFlagsMap); _treatAllCodeAsNonGeneratedCode = ShouldTreatAllCodeAsNonGeneratedCode(unsuppressedAnalyzers, _generatedCodeAnalysisFlagsMap);
_lazyGeneratedCodeFilesMap = _treatAllCodeAsNonGeneratedCode ? null : new Dictionary<SyntaxTree, bool>(); _lazyGeneratedCodeFilesMap = _treatAllCodeAsNonGeneratedCode ? null : new ConcurrentDictionary<SyntaxTree, bool>();
_lazyGeneratedCodeSymbolsMap = _treatAllCodeAsNonGeneratedCode ? null : new Dictionary<SyntaxTree, ImmutableHashSet<ISymbol>>(); _lazyGeneratedCodeSymbolsMap = _treatAllCodeAsNonGeneratedCode ? null : new Dictionary<SyntaxTree, ImmutableHashSet<ISymbol>>();
_lazyTreesWithHiddenRegionsMap = _treatAllCodeAsNonGeneratedCode ? null : new Dictionary<SyntaxTree, bool>(); _lazyTreesWithHiddenRegionsMap = _treatAllCodeAsNonGeneratedCode ? null : new ConcurrentDictionary<SyntaxTree, bool>();
_generatedCodeAttribute = analyzerExecutor.Compilation?.GetTypeByMetadataName("System.CodeDom.Compiler.GeneratedCodeAttribute"); _generatedCodeAttribute = analyzerExecutor.Compilation?.GetTypeByMetadataName("System.CodeDom.Compiler.GeneratedCodeAttribute");
_symbolActionsByKind = MakeSymbolActionsByKind(); _symbolActionsByKind = MakeSymbolActionsByKind();
...@@ -1288,6 +1289,9 @@ private bool IsGeneratedCodeSymbol(ISymbol symbol) ...@@ -1288,6 +1289,9 @@ private bool IsGeneratedCodeSymbol(ISymbol symbol)
return true; return true;
} }
[PerformanceSensitive(
"https://github.com/dotnet/roslyn/pull/23637",
AllowLocks = false)]
protected bool IsGeneratedCode(SyntaxTree tree) protected bool IsGeneratedCode(SyntaxTree tree)
{ {
if (_treatAllCodeAsNonGeneratedCode) if (_treatAllCodeAsNonGeneratedCode)
...@@ -1297,17 +1301,14 @@ protected bool IsGeneratedCode(SyntaxTree tree) ...@@ -1297,17 +1301,14 @@ protected bool IsGeneratedCode(SyntaxTree tree)
Debug.Assert(_lazyGeneratedCodeFilesMap != null); Debug.Assert(_lazyGeneratedCodeFilesMap != null);
lock (_lazyGeneratedCodeFilesMap) bool isGenerated;
if (!_lazyGeneratedCodeFilesMap.TryGetValue(tree, out isGenerated))
{ {
bool isGenerated; isGenerated = _isGeneratedCode(tree, analyzerExecutor.CancellationToken);
if (!_lazyGeneratedCodeFilesMap.TryGetValue(tree, out isGenerated)) _lazyGeneratedCodeFilesMap.TryAdd(tree, isGenerated);
{
isGenerated = _isGeneratedCode(tree, analyzerExecutor.CancellationToken);
_lazyGeneratedCodeFilesMap.Add(tree, isGenerated);
}
return isGenerated;
} }
return isGenerated;
} }
protected bool DoNotAnalyzeGeneratedCode => _doNotAnalyzeGeneratedCode; protected bool DoNotAnalyzeGeneratedCode => _doNotAnalyzeGeneratedCode;
...@@ -1320,6 +1321,9 @@ protected bool IsHiddenSourceLocation(SyntaxTree syntaxTree, TextSpan span) ...@@ -1320,6 +1321,9 @@ protected bool IsHiddenSourceLocation(SyntaxTree syntaxTree, TextSpan span)
=> HasHiddenRegions(syntaxTree) && => HasHiddenRegions(syntaxTree) &&
syntaxTree.IsHiddenPosition(span.Start); syntaxTree.IsHiddenPosition(span.Start);
[PerformanceSensitive(
"https://github.com/dotnet/roslyn/pull/23637",
AllowLocks = false)]
private bool HasHiddenRegions(SyntaxTree tree) private bool HasHiddenRegions(SyntaxTree tree)
{ {
Debug.Assert(tree != null); Debug.Assert(tree != null);
...@@ -1329,17 +1333,14 @@ private bool HasHiddenRegions(SyntaxTree tree) ...@@ -1329,17 +1333,14 @@ private bool HasHiddenRegions(SyntaxTree tree)
return false; return false;
} }
lock (_lazyTreesWithHiddenRegionsMap) bool hasHiddenRegions;
if (!_lazyTreesWithHiddenRegionsMap.TryGetValue(tree, out hasHiddenRegions))
{ {
bool hasHiddenRegions; hasHiddenRegions = tree.HasHiddenRegions();
if (!_lazyTreesWithHiddenRegionsMap.TryGetValue(tree, out hasHiddenRegions)) _lazyTreesWithHiddenRegionsMap.TryAdd(tree, hasHiddenRegions);
{
hasHiddenRegions = tree.HasHiddenRegions();
_lazyTreesWithHiddenRegionsMap.Add(tree, hasHiddenRegions);
}
return hasHiddenRegions;
} }
return hasHiddenRegions;
} }
internal async Task<AnalyzerActionCounts> GetAnalyzerActionCountsAsync(DiagnosticAnalyzer analyzer, CompilationOptions compilationOptions, CancellationToken cancellationToken) internal async Task<AnalyzerActionCounts> GetAnalyzerActionCountsAsync(DiagnosticAnalyzer analyzer, CompilationOptions compilationOptions, CancellationToken cancellationToken)
......
...@@ -64,6 +64,15 @@ public bool AllowGenericEnumeration ...@@ -64,6 +64,15 @@ public bool AllowGenericEnumeration
set; set;
} }
/// <summary>
/// Gets or sets a value indicating whether locks are allowed.
/// </summary>
public bool AllowLocks
{
get;
set;
}
/// <summary> /// <summary>
/// Gets or sets a value indicating whether the asynchronous state machine typically completes synchronously. /// Gets or sets a value indicating whether the asynchronous state machine typically completes synchronously.
/// </summary> /// </summary>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册