提交 0ad3ed0f 编写于 作者: H Heejae Chang

back ported only portion that is causing perf issues in dev15.4.x from master.

this basically prevent symbol info indexer from creating/calculating same checksum again and again for every documents in the solution.

this should make it to do it only once per project rather than document, and only update it when there is a change in the project.
上级 eb3f5baa
......@@ -150,9 +150,12 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference
{
// We can reuse the index for any given reference as long as it hasn't changed.
// So our checksum is just the checksum for the PEReference itself.
var serializer = new Serializer(solution.Workspace);
var checksum = serializer.CreateChecksum(reference, cancellationToken);
return checksum;
return ChecksumCache.GetOrCreate(reference, _ =>
{
var serializer = new Serializer(solution.Workspace);
var checksum = serializer.CreateChecksum(reference, cancellationToken);
return checksum;
});
}
private static Task<SymbolTreeInfo> TryLoadOrCreateMetadataSymbolTreeInfoAsync(
......
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Collections;
......@@ -41,7 +40,22 @@ private static void FreeSymbolMap(MultiDictionary<string, ISymbol> symbolMap)
return result;
}
public static async Task<Checksum> GetSourceSymbolsChecksumAsync(Project project, CancellationToken cancellationToken)
/// <summary>
/// Cache of project to the checksum for it so that we don't have to expensively recompute
/// this each time we get a project.
/// </summary>
private static ConditionalWeakTable<ProjectState, AsyncLazy<Checksum>> s_projectToSourceChecksum =
new ConditionalWeakTable<ProjectState, AsyncLazy<Checksum>>();
public static Task<Checksum> GetSourceSymbolsChecksumAsync(Project project, CancellationToken cancellationToken)
{
var lazy = s_projectToSourceChecksum.GetValue(
project.State, p => new AsyncLazy<Checksum>(c => ComputeSourceSymbolsChecksumAsync(p, c), cacheResult: true));
return lazy.GetValueAsync(cancellationToken);
}
private static async Task<Checksum> ComputeSourceSymbolsChecksumAsync(ProjectState projectState, CancellationToken cancellationToken)
{
// The SymbolTree for source is built from the source-symbols from the project's compilation's
// assembly. Specifically, we only get the name, kind and parent/child relationship of all the
......@@ -49,14 +63,14 @@ public static async Task<Checksum> GetSourceSymbolsChecksumAsync(Project project
// changed. The only thing that can make those source-symbols change in that manner are if
// the text of any document changes, or if options for the project change. So we build our
// checksum out of that data.
var serializer = new Serializer(project.Solution.Workspace);
var projectStateChecksums = await project.State.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false);
var serializer = new Serializer(projectState.LanguageServices.WorkspaceServices);
var projectStateChecksums = await projectState.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false);
// Order the documents by FilePath. Default ordering in the RemoteWorkspace is
// to be ordered by Guid (which is not consistent across VS sessions).
var textChecksumsTasks = project.Documents.OrderBy(d => d.FilePath).Select(async d =>
var textChecksumsTasks = projectState.DocumentStates.OrderBy(d => d.Value.FilePath).Select(async d =>
{
var documentStateChecksum = await d.State.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false);
var documentStateChecksum = await d.Value.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false);
return documentStateChecksum.Text;
});
......@@ -96,7 +110,7 @@ public static async Task<Checksum> GetSourceSymbolsChecksumAsync(Project project
GenerateSourceNodes(assembly.GlobalNamespace, unsortedNodes, s_getMembersNoPrivate);
return CreateSymbolTreeInfo(
project.Solution, checksum, project.FilePath, unsortedNodes.ToImmutableAndFree(),
project.Solution, checksum, project.FilePath, unsortedNodes.ToImmutableAndFree(),
inheritanceMap: new OrderPreservingMultiDictionary<string, string>());
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册