提交 400be5d9 编写于 作者: M Manish Vasani

Optimize performance for LookupSymbols(name)

A customer trace on recent 15.3 release shows that `Microsoft.CodeAnalysis.CSharp!Binder.IsAccessibleHelper` is taking up large amount of CPU stacks for LookupSymbols(name) calls from IDE analyzers. This change optimizes the performance of this code path by adding a name check before doing accessibilty checks.
上级 39a38b6e
......@@ -1240,12 +1240,19 @@ private CSDiagnosticInfo MakeCallMethodsDirectlyDiagnostic(Symbol symbol)
/// <remarks>
/// Does not consider <see cref="Symbol.CanBeReferencedByName"/> - that is left to the caller.
/// </remarks>
internal bool CanAddLookupSymbolInfo(Symbol symbol, LookupOptions options, TypeSymbol accessThroughType)
internal bool CanAddLookupSymbolInfo(Symbol symbol, LookupOptions options, LookupSymbolsInfo info, TypeSymbol accessThroughType, AliasSymbol aliasSymbol = null)
{
Debug.Assert(symbol.Kind != SymbolKind.Alias, "It is the caller's responsibility to unwrap aliased symbols.");
Debug.Assert(aliasSymbol == null || aliasSymbol.GetAliasTarget(basesBeingResolved: null) == symbol);
Debug.Assert(options.AreValid());
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
var name = aliasSymbol != null ? aliasSymbol.Name : symbol.Name;
if (!info.CanBeAdded(name))
{
return false;
}
if ((options & LookupOptions.NamespacesOrTypesOnly) != 0 && !(symbol is NamespaceOrTypeSymbol))
{
return false;
......@@ -1559,7 +1566,7 @@ private static void AddMemberLookupSymbolsInfoInNamespace(LookupSymbolsInfo resu
{
foreach (var symbol in GetCandidateMembers(ns, options, originalBinder))
{
if (originalBinder.CanAddLookupSymbolInfo(symbol, options, null))
if (originalBinder.CanAddLookupSymbolInfo(symbol, options, result, null))
{
result.AddSymbol(symbol, symbol.Name, symbol.GetArity());
}
......@@ -1570,7 +1577,7 @@ private static void AddMemberLookupSymbolsInfoWithoutInheritance(LookupSymbolsIn
{
foreach (var symbol in GetCandidateMembers(type, options, originalBinder))
{
if (originalBinder.CanAddLookupSymbolInfo(symbol, options, accessThroughType))
if (originalBinder.CanAddLookupSymbolInfo(symbol, options, result, accessThroughType))
{
result.AddSymbol(symbol, symbol.Name, symbol.GetArity());
}
......
......@@ -838,7 +838,7 @@ internal void AddLookupSymbolsInfoInAliases(LookupSymbolsInfo result, LookupOpti
private static void AddAliasSymbolToResult(LookupSymbolsInfo result, AliasSymbol aliasSymbol, LookupOptions options, Binder originalBinder)
{
var targetSymbol = aliasSymbol.GetAliasTarget(basesBeingResolved: null);
if (originalBinder.CanAddLookupSymbolInfo(targetSymbol, options, null))
if (originalBinder.CanAddLookupSymbolInfo(targetSymbol, options, result, accessThroughType: null, aliasSymbol: aliasSymbol))
{
result.AddSymbol(aliasSymbol, aliasSymbol.Name, 0);
}
......@@ -859,7 +859,7 @@ private static void AddAliasSymbolToResult(LookupSymbolsInfo result, AliasSymbol
{
foreach (var member in namespaceSymbol.NamespaceOrType.GetMembersUnordered())
{
if (IsValidLookupCandidateInUsings(member) && originalBinder.CanAddLookupSymbolInfo(member, options, null))
if (IsValidLookupCandidateInUsings(member) && originalBinder.CanAddLookupSymbolInfo(member, options, result, null))
{
result.AddSymbol(member, member.Name, member.GetArity());
}
......
......@@ -224,7 +224,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var parameter in _methodSymbol.Parameters)
{
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null))
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, result, null))
{
result.AddSymbol(parameter, parameter.Name, 0);
}
......
......@@ -399,7 +399,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var local in this.LocalsMap)
{
if (originalBinder.CanAddLookupSymbolInfo(local.Value, options, null))
if (originalBinder.CanAddLookupSymbolInfo(local.Value, options, result, null))
{
result.AddSymbol(local.Value, local.Key, 0);
}
......@@ -409,7 +409,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var local in this.LocalFunctionsMap)
{
if (originalBinder.CanAddLookupSymbolInfo(local.Value, options, null))
if (originalBinder.CanAddLookupSymbolInfo(local.Value, options, result, null))
{
result.AddSymbol(local.Value, local.Key, 0);
}
......
......@@ -51,7 +51,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var parameter in _namedType.TypeParameters)
{
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null))
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, result, null))
{
result.AddSymbol(parameter, parameter.Name, 0);
}
......
......@@ -141,7 +141,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
foreach (TypeParameterSymbol typeParameter in kvp.Value)
{
// In any context where this binder applies, the type parameters are always viable/speakable.
Debug.Assert(originalBinder.CanAddLookupSymbolInfo(typeParameter, options, null));
Debug.Assert(!result.CanBeAdded(typeParameter.Name) || originalBinder.CanAddLookupSymbolInfo(typeParameter, options, result, null));
result.AddSymbol(typeParameter, kvp.Key, 0);
}
......
......@@ -100,7 +100,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var parameter in lambdaSymbol.Parameters)
{
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null))
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, result, null))
{
result.AddSymbol(parameter, parameter.Name, 0);
}
......
......@@ -61,7 +61,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var parameter in _methodSymbol.TypeParameters)
{
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null))
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, result, null))
{
result.AddSymbol(parameter, parameter.Name, 0);
}
......
......@@ -29,7 +29,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var parameter in _parameters)
{
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null))
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, result, null))
{
result.AddSymbol(parameter, parameter.Name, 0);
}
......
......@@ -1510,6 +1510,7 @@ private void CheckModelAndSyntaxNodeToSpeculate(CSharpSyntaxNode syntax)
}
var info = LookupSymbolsInfo.GetInstance();
info.FilterName = name;
if ((object)container == null)
{
......
......@@ -222,13 +222,18 @@ public int Count
#endif
}
private readonly IEqualityComparer<string> _comparer;
private readonly Dictionary<string, UniqueSymbolOrArities> _nameMap;
internal string FilterName { private get; set; }
protected AbstractLookupSymbolsInfo(IEqualityComparer<string> comparer)
{
_comparer = comparer;
_nameMap = new Dictionary<string, UniqueSymbolOrArities>(comparer);
}
public bool CanBeAdded(string name) => FilterName == null || _comparer.Equals(name, FilterName);
public void AddSymbol(TSymbol symbol, string name, int arity)
{
UniqueSymbolOrArities pair;
......@@ -273,6 +278,8 @@ public void AddSymbol(TSymbol symbol, string name, int arity)
out IArityEnumerable arities,
out TSymbol uniqueSymbol)
{
Debug.Assert(CanBeAdded(name));
UniqueSymbolOrArities pair;
if (!_nameMap.TryGetValue(name, out pair))
{
......@@ -287,6 +294,10 @@ public void AddSymbol(TSymbol symbol, string name, int arity)
return true;
}
public void Clear() => _nameMap.Clear();
public void Clear()
{
_nameMap.Clear();
FilterName = null;
}
}
}
......@@ -274,11 +274,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' </remarks>
Friend Function CanAddLookupSymbolInfo(sym As Symbol,
options As LookupOptions,
nameSet As LookupSymbolsInfo,
accessThroughType As TypeSymbol) As Boolean
Debug.Assert(sym IsNot Nothing)
If Not nameSet.CanBeAdded(sym.Name) Then
Return False
End If
Dim singleResult = CheckViability(sym, -1, options, accessThroughType, useSiteDiagnostics:=Nothing)
If sym IsNot Nothing AndAlso
(options And LookupOptions.MethodsOnly) <> 0 AndAlso
If (options And LookupOptions.MethodsOnly) <> 0 AndAlso
sym.Kind <> SymbolKind.Method Then
Return False
End If
......@@ -524,7 +530,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' Add names from the namespace
For Each sym In container.GetMembersUnordered()
' UNDONE: filter by options
If binder.CanAddLookupSymbolInfo(sym, options, Nothing) Then
If binder.CanAddLookupSymbolInfo(sym, options, nameSet, Nothing) Then
nameSet.AddSymbol(sym, sym.Name, sym.GetArity())
End If
Next
......@@ -2081,7 +2087,7 @@ ExitForFor:
' validate them.
If TypeOf container Is NamedTypeSymbol Then
For Each sym In container.GetTypeMembersUnordered()
If binder.CanAddLookupSymbolInfo(sym, options, accessThroughType) Then
If binder.CanAddLookupSymbolInfo(sym, options, nameSet, accessThroughType) Then
nameSet.AddSymbol(sym, sym.Name, sym.Arity)
End If
Next
......@@ -2089,7 +2095,7 @@ ExitForFor:
ElseIf (options And LookupOptions.LabelsOnly) = 0 Then
' Go through each member of the type.
For Each sym In container.GetMembersUnordered()
If binder.CanAddLookupSymbolInfo(sym, options, accessThroughType) Then
If binder.CanAddLookupSymbolInfo(sym, options, nameSet, accessThroughType) Then
nameSet.AddSymbol(sym, sym.Name, sym.GetArity())
End If
Next
......
......@@ -89,7 +89,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim locals = Me.Locals
If Not locals.IsEmpty AndAlso (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly)) = 0 Then
For Each localSymbol In locals
If originalBinder.CanAddLookupSymbolInfo(localSymbol, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(localSymbol, options, nameSet, Nothing) Then
nameSet.AddSymbol(localSymbol, localSymbol.Name, 0)
End If
Next
......
......@@ -43,7 +43,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
originalBinder As Binder)
For Each typeParameter In _typeParameters.Values
If originalBinder.CanAddLookupSymbolInfo(typeParameter, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(typeParameter, options, nameSet, Nothing) Then
nameSet.AddSymbol(typeParameter, typeParameter.Name, 0)
End If
Next
......
......@@ -78,7 +78,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
For Each parameter In Me.Parameters
If originalBinder.CanAddLookupSymbolInfo(parameter, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(parameter, options, nameSet, Nothing) Then
nameSet.AddSymbol(parameter, parameter.Name, 0)
End If
Next
......
......@@ -60,7 +60,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If Not typeParameters.IsEmpty Then
For Each typeParameter In typeParameters
If originalBinder.CanAddLookupSymbolInfo(typeParameter, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(typeParameter, options, nameSet, Nothing) Then
nameSet.AddSymbol(typeParameter, typeParameter.Name, 0)
End If
Next
......
......@@ -231,7 +231,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
(options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly)) = 0 Then
For Each localSymbol In _implicitLocals.Values
If originalBinder.CanAddLookupSymbolInfo(localSymbol, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(localSymbol, options, nameSet, Nothing) Then
nameSet.AddSymbol(localSymbol, localSymbol.Name, 0)
End If
Next
......
......@@ -57,7 +57,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
originalBinder As Binder)
' UNDONE: check options to see if type parameters should be found.
For Each typeParameter In _typeParameters
If originalBinder.CanAddLookupSymbolInfo(typeParameter, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(typeParameter, options, nameSet, Nothing) Then
nameSet.AddSymbol(typeParameter, typeParameter.Name, 0)
End If
Next
......
......@@ -113,7 +113,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' UNDONE: filter using options.
If _typeSymbol.Arity > 0 Then
For Each tp In _typeSymbol.TypeParameters
If originalBinder.CanAddLookupSymbolInfo(tp, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(tp, options, nameSet, Nothing) Then
nameSet.AddSymbol(tp, tp.Name, 0)
End If
Next
......
......@@ -75,7 +75,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' UNDONE: additional filtering based on options?
If (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly)) = 0 Then
For Each param In _parameterMap.Values
If originalBinder.CanAddLookupSymbolInfo(param, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(param, options, nameSet, Nothing) Then
nameSet.AddSymbol(param, param.Name, 0)
End If
Next
......
......@@ -1890,6 +1890,8 @@ _Default:
Else
' They provided a name. Find all the arities for that name, and then look all of those up.
Dim info = LookupSymbolsInfo.GetInstance()
info.FilterName = name
Me.AddLookupSymbolsInfo(position, info, container, options)
Dim results = ArrayBuilder(Of Symbol).GetInstance(info.Count)
......
......@@ -215,7 +215,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
If method.MayBeReducibleExtensionMethod Then
haveSeenExtensionMethod = True
If AddExtensionMethodLookupSymbolsInfoViabilityCheck(method, options, originalBinder) Then
If AddExtensionMethodLookupSymbolsInfoViabilityCheck(method, options, nameSet, originalBinder) Then
nameSet.AddSymbol(member, member.Name, member.GetArity())
' Move to the next name.
......@@ -239,9 +239,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Friend Overridable Function AddExtensionMethodLookupSymbolsInfoViabilityCheck(
method As MethodSymbol,
options As LookupOptions,
nameSet As LookupSymbolsInfo,
originalBinder As Binder
) As Boolean
Return originalBinder.CanAddLookupSymbolInfo(method, options, accessThroughType:=method.ContainingType)
Return originalBinder.CanAddLookupSymbolInfo(method, options, nameSet, accessThroughType:=method.ContainingType)
End Function
''' <summary>
......
......@@ -214,8 +214,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
''' <summary>
''' Make sure we retarget methods when underlying type checks their viability.
''' </summary>
Friend Overrides Function AddExtensionMethodLookupSymbolsInfoViabilityCheck(method As MethodSymbol, options As LookupOptions, originalBinder As Binder) As Boolean
Return MyBase.AddExtensionMethodLookupSymbolsInfoViabilityCheck(RetargetingTranslator.Retarget(method), options, originalBinder)
Friend Overrides Function AddExtensionMethodLookupSymbolsInfoViabilityCheck(method As MethodSymbol, options As LookupOptions, nameSet As LookupSymbolsInfo, originalBinder As Binder) As Boolean
Return MyBase.AddExtensionMethodLookupSymbolsInfoViabilityCheck(RetargetingTranslator.Retarget(method), options, nameSet, originalBinder)
End Function
Friend Overrides Sub AddExtensionMethodLookupSymbolsInfo(nameSet As LookupSymbolsInfo,
......
......@@ -270,8 +270,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting
''' <summary>
''' Make sure we retarget methods when underlying namespace checks their viability.
''' </summary>
Friend Overrides Function AddExtensionMethodLookupSymbolsInfoViabilityCheck(method As MethodSymbol, options As LookupOptions, originalBinder As Binder) As Boolean
Return MyBase.AddExtensionMethodLookupSymbolsInfoViabilityCheck(RetargetingTranslator.Retarget(method), options, originalBinder)
Friend Overrides Function AddExtensionMethodLookupSymbolsInfoViabilityCheck(method As MethodSymbol, options As LookupOptions, nameSet As LookupSymbolsInfo, originalBinder As Binder) As Boolean
Return MyBase.AddExtensionMethodLookupSymbolsInfoViabilityCheck(RetargetingTranslator.Retarget(method), options, nameSet, originalBinder)
End Function
Friend Overrides Sub AddExtensionMethodLookupSymbolsInfo(nameSet As LookupSymbolsInfo,
......
......@@ -45,7 +45,7 @@ protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo res
{
foreach (var parameter in _typeArguments)
{
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null))
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, result, null))
{
result.AddSymbol(parameter, parameter.Name, 0);
}
......
......@@ -91,7 +91,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
' UNDONE: additional filtering based on options?
If (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly Or LookupOptions.MustNotBeLocalOrParameter)) = 0 Then
For Each symbol In _nameToSymbolMap.Values
If originalBinder.CanAddLookupSymbolInfo(symbol, options, Nothing) Then
If originalBinder.CanAddLookupSymbolInfo(symbol, options, nameSet, Nothing) Then
nameSet.AddSymbol(symbol, symbol.Name, 0)
End If
Next
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册