From b99d0b385818948f3e827e33ea8748450c8d64b6 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 31 Jan 2018 08:57:06 -0600 Subject: [PATCH] Parallelize namespace members when analyzing the entire compilation --- .../Portable/Compiler/ClsComplianceChecker.cs | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs b/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs index 4054eb610b2..a2ee137f2d8 100644 --- a/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs +++ b/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs @@ -1,10 +1,12 @@ // 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.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -24,6 +26,9 @@ internal partial class ClsComplianceChecker : CSharpSymbolVisitor private readonly ConcurrentDictionary _declaredOrInheritedCompliance; + /// + private ConcurrentStack _compilerTasks; + private ClsComplianceChecker( CSharpCompilation compilation, SyntaxTree filterTree, @@ -52,7 +57,13 @@ public static void CheckCompliance(CSharpCompilation compilation, DiagnosticBag { var queue = new ConcurrentQueue(); var checker = new ClsComplianceChecker(compilation, filterTree, filterSpanWithinTree, queue, cancellationToken); + if (compilation.Options.ConcurrentBuild) + { + checker._compilerTasks = new ConcurrentStack(); + } + checker.Visit(compilation.Assembly); + checker.WaitForWorkers(); foreach (Diagnostic diag in queue) { @@ -145,7 +156,20 @@ public override void VisitAssembly(AssemblySymbol symbol) Visit(symbol.GlobalNamespace); } - [PerformanceSensitive("https://github.com/dotnet/roslyn/issues/23582", IsParallelEntry = false)] + private void WaitForWorkers() + { + var tasks = _compilerTasks; + if (tasks == null) + { + return; + } + + while (tasks.TryPop(out Task curTask)) + { + curTask.GetAwaiter().GetResult(); + } + } + public override void VisitNamespace(NamespaceSymbol symbol) { _cancellationToken.ThrowIfCancellationRequested(); @@ -158,6 +182,36 @@ public override void VisitNamespace(NamespaceSymbol symbol) CheckMemberDistinctness(symbol); } + if (_filterTree == null && _compilation.Options.ConcurrentBuild) + { + VisitNamespaceMembersAsTasks(symbol); + } + else + { + VisitNamespaceMembers(symbol); + } + } + + private void VisitNamespaceMembersAsTasks(NamespaceSymbol symbol) + { + foreach (var m in symbol.GetMembersUnordered()) + { + _compilerTasks.Push(Task.Run(UICultureUtilities.WithCurrentUICulture(() => + { + try + { + Visit(m); + } + catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) + { + throw ExceptionUtilities.Unreachable; + } + }), _cancellationToken)); + } + } + + private void VisitNamespaceMembers(NamespaceSymbol symbol) + { foreach (var m in symbol.GetMembersUnordered()) { Visit(m); -- GitLab