提交 fdfc978b 编写于 作者: C CyrusNajmabadi

Improve add-using perf in interactive window.

1. When creating symbol tree infos, lazily produce BKtrees.  That way we don't
   take the perf hit for features that want to search but don't need fuzzy matching

2. Don't perform fuzzy matching interactive.  The problem here is that interactive
   Doesn't have a 'serialization service'.  As such, when VS loads and we run
   interactive, we end up having to produce all the same BKtrees for metadata again.
   In normal scenarios we can store these in the .vs file, so we only pay the price
   the very first time.  In Interactive we always pay the price the first time
   after VS loads.
上级 f4908236
......@@ -84,7 +84,14 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (allSymbolReferences.Count == 0)
{
// No exact matches found. Fall back to fuzzy searching.
await FindResults(projectToAssembly, referenceToCompilation, project, allSymbolReferences, finder, exact: false, cancellationToken: cancellationToken).ConfigureAwait(false);
// Only bother doing this for host workspaces. We don't want this for
// things like the Interactive workspace as this will cause us to
// create expensive bktrees which we won't even be able to save for
// future use.
if (document.Project.Solution.Workspace.Kind == WorkspaceKind.Host)
{
await FindResults(projectToAssembly, referenceToCompilation, project, allSymbolReferences, finder, exact: false, cancellationToken: cancellationToken).ConfigureAwait(false);
}
}
// Nothing found at all. No need to proceed.
......
......@@ -25,7 +25,7 @@ internal partial class SymbolTreeInfo
/// <summary>
/// The spell checker we use for fuzzy match queries.
/// </summary>
private readonly SpellChecker _spellChecker;
private readonly Lazy<SpellChecker> _lazySpellChecker;
private static readonly StringComparer s_caseInsensitiveComparer = CaseInsensitiveComparison.Comparer;
......@@ -45,11 +45,25 @@ internal partial class SymbolTreeInfo
: StringComparer.Ordinal.Compare(s1, s2);
};
private SymbolTreeInfo(VersionStamp version, IReadOnlyList<Node> orderedNodes)
: this(version, orderedNodes, new Lazy<SpellChecker>(() => new SpellChecker(orderedNodes.Select(n => n.Name))))
{
}
private SymbolTreeInfo(VersionStamp version, IReadOnlyList<Node> orderedNodes, SpellChecker spellChecker)
: this(version, orderedNodes, new Lazy<SpellChecker>(() => spellChecker))
{
// Make the lazy 'Created'. This is a no-op since we already have the underlying spell
// checker. This way if we end up wanting to serialize this tree info, we'll also
// serialize the spell checker.
var unused = _lazySpellChecker.Value;
}
private SymbolTreeInfo(VersionStamp version, IReadOnlyList<Node> orderedNodes, Lazy<SpellChecker> lazySpellChecker)
{
_version = version;
_nodes = orderedNodes;
_spellChecker = spellChecker;
_lazySpellChecker = lazySpellChecker;
}
public int Count => _nodes.Count;
......@@ -84,7 +98,7 @@ public Task<IEnumerable<ISymbol>> FindAsync(SearchQuery query, AsyncLazy<IAssemb
/// </summary>
public async Task<IEnumerable<ISymbol>> FuzzyFindAsync(AsyncLazy<IAssemblySymbol> lazyAssembly, string name, CancellationToken cancellationToken)
{
var similarNames = _spellChecker.FindSimilarWords(name);
var similarNames = _lazySpellChecker.Value.FindSimilarWords(name);
var result = new List<ISymbol>();
foreach (var similarName in similarNames)
......@@ -291,8 +305,7 @@ internal static SymbolTreeInfo Create(VersionStamp version, IAssemblySymbol asse
var list = new List<Node>();
GenerateNodes(assembly.GlobalNamespace, list);
var spellChecker = new SpellChecker(list.Select(n => n.Name));
return new SymbolTreeInfo(version, SortNodes(list), spellChecker);
return new SymbolTreeInfo(version, SortNodes(list));
}
private static Node[] SortNodes(List<Node> nodes)
......
......@@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols
internal partial class SymbolTreeInfo : IObjectWritable
{
private const string PrefixMetadataSymbolTreeInfo = "<MetadataSymbolTreeInfoPersistence>_";
private const string SerializationFormat = "9";
private const string SerializationFormat = "10";
private static bool ShouldCreateFromScratch(
Solution solution,
......@@ -123,7 +123,15 @@ public void WriteTo(ObjectWriter writer)
writer.WriteInt32(node.ParentIndex);
}
_spellChecker.WriteTo(writer);
if (_lazySpellChecker.IsValueCreated)
{
writer.WriteBoolean(true);
_lazySpellChecker.Value.WriteTo(writer);
}
else
{
writer.WriteBoolean(false);
}
}
internal static SymbolTreeInfo ReadFrom(ObjectReader reader)
......@@ -141,7 +149,7 @@ internal static SymbolTreeInfo ReadFrom(ObjectReader reader)
var count = reader.ReadInt32();
if (count == 0)
{
return new SymbolTreeInfo(version, ImmutableArray<Node>.Empty, SpellChecker.Empty);
return new SymbolTreeInfo(version, ImmutableArray<Node>.Empty);
}
var nodes = new Node[count];
......@@ -153,7 +161,10 @@ internal static SymbolTreeInfo ReadFrom(ObjectReader reader)
nodes[i] = new Node(name, parentIndex);
}
return new SymbolTreeInfo(version, nodes, SpellChecker.ReadFrom(reader));
var hasSpellChecker = reader.ReadBoolean();
return hasSpellChecker
? new SymbolTreeInfo(version, nodes, SpellChecker.ReadFrom(reader))
: new SymbolTreeInfo(version, nodes);
}
catch (Exception)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册