From c983c3accc73a9161c225cb61c48c4044dd6d062 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 10 Jun 2020 22:08:29 -0700 Subject: [PATCH 1/4] Process projects in parallel in FAR> --- .../FindReferencesSearchEngine.cs | 26 ++------ ...eferencesSearchEngine_ProjectProcessing.cs | 64 +------------------ 2 files changed, 7 insertions(+), 83 deletions(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs index 2c90cab0039c..3002131b7673 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.FindSymbols.Finders; using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Utilities; using Roslyn.Utilities; @@ -78,33 +79,18 @@ private async Task ProcessAsync(ProjectToDocumentMap projectToDocumentMap) return; } - // Get the connected components of the dependency graph and process each individually. - // That way once a component is done we can throw away all the memory associated with - // it. - // For each connected component, we'll process the individual projects from bottom to - // top. i.e. we'll first process the projects with no dependencies. Then the projects - // that depend on those projects, and so on. This way we always have created the - // dependent compilations when they're needed by later projects. If we went the other - // way (i.e. processed the projects with lots of project dependencies first), then we'd - // have to create all their dependent compilations in order to get their compilation. - // This would be very expensive and would take a lot of time before we got our first - // result. - var connectedProjects = _dependencyGraph.GetDependencySets(_cancellationToken); - // Add a progress item for each (document, symbol, finder) set that we will execute. // We'll mark the item as completed in "ProcessDocumentAsync". var totalFindCount = projectToDocumentMap.Sum( kvp1 => kvp1.Value.Sum(kvp2 => kvp2.Value.Count)); await _progressTracker.AddItemsAsync(totalFindCount).ConfigureAwait(false); - // Now, go through each connected project set and process it independently. - foreach (var connectedProjectSet in connectedProjects) - { - _cancellationToken.ThrowIfCancellationRequested(); + using var _ = ArrayBuilder.GetInstance(out var tasks); - await ProcessProjectsAsync( - connectedProjectSet, projectToDocumentMap).ConfigureAwait(false); - } + foreach (var (project, documentMap) in projectToDocumentMap) + tasks.Add(Task.Run(() => ProcessProjectAsync(project, documentMap), _cancellationToken)); + + await Task.WhenAll(tasks).ConfigureAwait(false); } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs index f00b242cc025..365921bd4f88 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs @@ -12,72 +12,10 @@ namespace Microsoft.CodeAnalysis.FindSymbols { using DocumentMap = MultiDictionary; - using ProjectToDocumentMap = Dictionary>; internal partial class FindReferencesSearchEngine { - private async Task ProcessProjectsAsync( - IEnumerable connectedProjectSet, - ProjectToDocumentMap projectToDocumentMap) - { - var visitedProjects = new HashSet(); - - // Make sure we process each project in the set. Process each project in depth first - // order. That way when we process a project, the compilations for all projects that it - // depends on will have been created already. - foreach (var projectId in connectedProjectSet) - { - _cancellationToken.ThrowIfCancellationRequested(); - - await ProcessProjectAsync( - projectId, projectToDocumentMap, visitedProjects).ConfigureAwait(false); - } - } - - private async Task ProcessProjectAsync( - ProjectId projectId, - ProjectToDocumentMap projectToDocumentMap, - HashSet visitedProjects) - { - // Don't visit projects more than once. - if (visitedProjects.Add(projectId)) - { - var project = _solution.GetProject(projectId); - - // Visit dependencies first. That way the compilation for a project that we depend - // on is already ready for us when we need it. - foreach (var dependent in project.ProjectReferences) - { - _cancellationToken.ThrowIfCancellationRequested(); - - await ProcessProjectAsync( - dependent.ProjectId, projectToDocumentMap, visitedProjects).ConfigureAwait(false); - } - - await ProcessProjectAsync(project, projectToDocumentMap).ConfigureAwait(false); - } - } - - private async Task ProcessProjectAsync( - Project project, - ProjectToDocumentMap projectToDocumentMap) - { - if (!projectToDocumentMap.TryGetValue(project, out var documentMap)) - { - // No files in this project to process. We can bail here. We'll have cached our - // compilation if there are any projects left to process that depend on us. - return; - } - - projectToDocumentMap.Remove(project); - - // Now actually process the project. - await ProcessProjectAsync(project, documentMap).ConfigureAwait(false); - } - - private async Task ProcessProjectAsync( - Project project, - DocumentMap documentMap) + private async Task ProcessProjectAsync(Project project, DocumentMap documentMap) { using (Logger.LogBlock(FunctionId.FindReference_ProcessProjectAsync, project.Name, _cancellationToken)) { From dd5f432ebced1f36c8939d73d0f3ae885eab246f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 11 Jun 2020 00:34:14 -0700 Subject: [PATCH 2/4] Fix --- .../Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs | 2 +- .../FindSymbols/FindReferences/FindReferencesSearchEngine.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs index 4abd2f3107d8..00318fc564c1 100644 --- a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs +++ b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs @@ -161,7 +161,7 @@ private async Task CheckItemsAsync( } var insertionText = await GetInsertionTextAsync(document, item, completionList.Span, cancellationToken: cancellationToken).ConfigureAwait(false); - results.Add(matchCost, insertionText); + results.Add(matchCost, insertionText ); } var nameText = nameToken.ValueText; diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs index 3002131b7673..7f2fc217d9df 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs @@ -26,7 +26,6 @@ internal partial class FindReferencesSearchEngine private readonly IStreamingProgressTracker _progressTracker; private readonly IStreamingFindReferencesProgress _progress; private readonly CancellationToken _cancellationToken; - private readonly ProjectDependencyGraph _dependencyGraph; private readonly FindReferencesSearchOptions _options; public FindReferencesSearchEngine( @@ -42,7 +41,6 @@ public FindReferencesSearchEngine( _finders = finders; _progress = progress; _cancellationToken = cancellationToken; - _dependencyGraph = solution.GetProjectDependencyGraph(); _options = options; _progressTracker = progress.ProgressTracker; From 12087719aa97007866389d5b41a1ef10932a8c33 Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Thu, 11 Jun 2020 01:23:30 -0700 Subject: [PATCH 3/4] Update src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs --- .../Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs index 00318fc564c1..4abd2f3107d8 100644 --- a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs +++ b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs @@ -161,7 +161,7 @@ private async Task CheckItemsAsync( } var insertionText = await GetInsertionTextAsync(document, item, completionList.Span, cancellationToken: cancellationToken).ConfigureAwait(false); - results.Add(matchCost, insertionText ); + results.Add(matchCost, insertionText); } var nameText = nameToken.ValueText; From 3e83fc75b9e17fbcccf46f2b1bec1de7f984f02b Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Thu, 11 Jun 2020 01:24:46 -0700 Subject: [PATCH 4/4] Update src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs --- .../FindReferencesSearchEngine_ProjectProcessing.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs index 365921bd4f88..18313c5dc796 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_ProjectProcessing.cs @@ -15,7 +15,9 @@ namespace Microsoft.CodeAnalysis.FindSymbols internal partial class FindReferencesSearchEngine { - private async Task ProcessProjectAsync(Project project, DocumentMap documentMap) + private async Task ProcessProjectAsync( + Project project, + DocumentMap documentMap) { using (Logger.LogBlock(FunctionId.FindReference_ProcessProjectAsync, project.Name, _cancellationToken)) {