From: Anubhav Srivastava Date: Fri, 6 Dec 2019 02:43:00 +0000 (-0800) Subject: Enable parallelism in Crossgen2 and add flags for it in SuperIlc. (#495) X-Git-Tag: submit/tizen/20210909.063632~10777 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=14a1cdb50f0341eddcef0160fece562c1c008e96;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Enable parallelism in Crossgen2 and add flags for it in SuperIlc. (#495) * Enable parallelism in Crossgen2 and add flags for it in SuperIlc. * Use fluent api pattern in ReadyToRunCodegenCompilationBuilder for resilient, IBC tuning, and parallelism flags. --- diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs index b3d2277..6316fd3 100644 --- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs +++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs @@ -28,6 +28,7 @@ namespace ReadyToRun.SuperIlc public bool UseFramework { get; set; } public bool Release { get; set; } public bool LargeBubble { get; set; } + public int Crossgen2Parallelism { get; set; } public int CompilationTimeoutMinutes { get; set; } public int ExecutionTimeoutMinutes { get; set; } public DirectoryInfo[] ReferencePath { get; set; } diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs index 5f9d92f..67460be 100644 --- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs +++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs @@ -44,6 +44,7 @@ namespace ReadyToRun.SuperIlc UseFramework(), Release(), LargeBubble(), + Crossgen2Parallelism(), ReferencePath(), IssuesPath(), CompilationTimeoutMinutes(), @@ -75,6 +76,7 @@ namespace ReadyToRun.SuperIlc UseFramework(), Release(), LargeBubble(), + Crossgen2Parallelism(), ReferencePath(), IssuesPath(), CompilationTimeoutMinutes(), @@ -195,6 +197,9 @@ namespace ReadyToRun.SuperIlc Option LargeBubble() => new Option(new[] { "--large-bubble" }, "Assume all input files as part of one version bubble", new Argument()); + Option Crossgen2Parallelism() => + new Option(new[] { "--crossgen2-parallelism" }, "Max number of threads to use in Crossgen2 (default = logical processor count)", new Argument()); + Option IssuesPath() => new Option(new[] { "--issues-path", "-ip" }, "Path to issues.targets", new Argument() { Arity = ArgumentArity.ZeroOrMore }); diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs index b8498b6..cce5f42 100644 --- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs +++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs @@ -25,7 +25,11 @@ namespace ReadyToRun.SuperIlc public CpaotRunner(BuildOptions options, IEnumerable referencePaths) : base(options, referencePaths) - { } + { + // Set SuperIlc parallelism to a low enough value that ensures that each Crossgen2 invocation gets to use its parallelism + if (options.DegreeOfParallelism == 0) + options.DegreeOfParallelism = 2; + } protected override ProcessParameters ExecutionProcess(IEnumerable modules, IEnumerable folders, bool noEtw) { @@ -55,6 +59,11 @@ namespace ReadyToRun.SuperIlc yield return "--inputbubble"; } + if (_options.Crossgen2Parallelism != 0) + { + yield return $"--parallelism={_options.Crossgen2Parallelism}"; + } + foreach (var reference in ComputeManagedAssemblies.GetManagedAssembliesInFolder(Path.GetDirectoryName(assemblyFileName))) { yield return $"-r:{reference}"; diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 25c0650..503fa4f 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -8,6 +8,7 @@ using System.IO; using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; using System.Threading; +using System.Threading.Tasks; using Internal.IL; using Internal.IL.Stubs; @@ -190,12 +191,20 @@ namespace ILCompiler private readonly JitConfigProvider _jitConfigProvider; /// + /// We only need one CorInfoImpl per thread, and we don't want to unnecessarily construct them + /// because their construction takes a significant amount of time. + /// + private readonly ConditionalWeakTable _corInfoImpls; + + /// /// Name of the compilation input MSIL file. /// private readonly string _inputFilePath; private bool _resilient; + private int _parallelism; + public new ReadyToRunCodegenNodeFactory NodeFactory { get; } public ReadyToRunSymbolNodeFactory SymbolNodeFactory { get; } @@ -210,16 +219,19 @@ namespace ILCompiler JitConfigProvider configProvider, string inputFilePath, IEnumerable modulesBeingInstrumented, - bool resilient) + bool resilient, + int parallelism) : base(dependencyGraph, nodeFactory, roots, ilProvider, devirtualizationManager, modulesBeingInstrumented, logger) { _resilient = resilient; + _parallelism = parallelism; NodeFactory = nodeFactory; SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory); _jitConfigProvider = configProvider; _inputFilePath = inputFilePath; + _corInfoImpls = new ConditionalWeakTable(); CorInfoImpl.RegisterJITModule(configProvider); } @@ -264,8 +276,11 @@ namespace ILCompiler { using (PerfEventSource.StartStopEvents.JitEvents()) { - ConditionalWeakTable cwt = new ConditionalWeakTable(); - foreach (DependencyNodeCore dependency in obj) + ParallelOptions options = new ParallelOptions + { + MaxDegreeOfParallelism = _parallelism + }; + Parallel.ForEach(obj, options, dependency => { MethodWithGCInfo methodCodeNodeNeedingCode = dependency as MethodWithGCInfo; MethodDesc method = methodCodeNodeNeedingCode.Method; @@ -280,7 +295,7 @@ namespace ILCompiler { using (PerfEventSource.StartStopEvents.JitMethodEvents()) { - CorInfoImpl corInfoImpl = cwt.GetValue(Thread.CurrentThread, thread => new CorInfoImpl(this)); + CorInfoImpl corInfoImpl = _corInfoImpls.GetValue(Thread.CurrentThread, thread => new CorInfoImpl(this)); corInfoImpl.CompileMethod(methodCodeNodeNeedingCode); } } @@ -297,7 +312,7 @@ namespace ILCompiler { Logger.Writer.WriteLine($"Warning: Method `{method}` was not compiled because `{ex.Message}` requires runtime JIT"); } - } + }); } if (_methodILCache.Count > 1000) diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index 0475c2c..5b1376b 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -20,8 +20,9 @@ namespace ILCompiler { private readonly string _inputFilePath; private readonly EcmaModule _inputModule; - private readonly bool _ibcTuning; - private readonly bool _resilient; + private bool _ibcTuning; + private bool _resilient; + private int _parallelism; private string _jitPath; // These need to provide reasonable defaults so that the user can optionally skip @@ -29,13 +30,10 @@ namespace ILCompiler private KeyValuePair[] _ryujitOptions = Array.Empty>(); private ILProvider _ilProvider = new ReadyToRunILProvider(); - public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group, string inputFilePath, bool ibcTuning, bool resilient) + public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group, string inputFilePath) : base(context, group, new CoreRTNameMangler()) { _inputFilePath = inputFilePath; - _ibcTuning = ibcTuning; - _resilient = resilient; - _inputModule = context.GetModuleFromPath(_inputFilePath); // R2R field layout needs compilation group information @@ -84,6 +82,25 @@ namespace ILCompiler return this; } + public ReadyToRunCodegenCompilationBuilder UseIbcTuning(bool ibcTuning) + { + _ibcTuning = ibcTuning; + return this; + } + + public ReadyToRunCodegenCompilationBuilder UseResilience(bool resilient) + { + _resilient = resilient; + return this; + } + + public ReadyToRunCodegenCompilationBuilder UseParallelism(int parallelism) + { + _parallelism = parallelism; + return this; + } + + public override ICompilation ToCompilation() { ModuleTokenResolver moduleTokenResolver = new ModuleTokenResolver(_compilationGroup, _context); @@ -167,7 +184,8 @@ namespace ILCompiler jitConfig, _inputFilePath, new ModuleDesc[] { _inputModule }, - _resilient); + _resilient, + _parallelism); } } } diff --git a/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs b/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs index c943984..61dd2a0 100644 --- a/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs +++ b/src/coreclr/src/tools/crossgen2/crossgen2/CommandLineOptions.cs @@ -31,6 +31,8 @@ namespace ILCompiler public bool Tuning { get; set; } public bool Partial { get; set; } public bool Resilient { get; set; } + public int Parallelism { get; set; } + public string SingleMethodTypeName { get; set; } public string SingleMethodName { get; set; } @@ -140,6 +142,10 @@ namespace ILCompiler // We don't need to override arity here as 255 is the maximum number of generic arguments Argument = new Argument() }, + new Option(new[] { "--parallelism" }, "Maximum number of threads to use during compilation") + { + Argument = new Argument(() => Environment.ProcessorCount) + }, }; } } diff --git a/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs b/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs index 4979d23..d0a7758 100644 --- a/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs +++ b/src/coreclr/src/tools/crossgen2/crossgen2/Program.cs @@ -311,10 +311,7 @@ namespace ILCompiler inputFilePath = input.Value; break; } - CompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath, - ibcTuning: _commandLineOptions.Tuning, - resilient: _commandLineOptions.Resilient); - + ReadyToRunCodegenCompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath); string compilationUnitPrefix = ""; builder.UseCompilationUnitPrefix(compilationUnitPrefix); @@ -324,6 +321,9 @@ namespace ILCompiler DependencyTrackingLevel.None : (_commandLineOptions.GenerateFullDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First); builder + .UseIbcTuning(_commandLineOptions.Tuning) + .UseResilience(_commandLineOptions.Resilient) + .UseParallelism(_commandLineOptions.Parallelism) .UseILProvider(ilProvider) .UseJitPath(_commandLineOptions.JitPath) .UseBackendOptions(_commandLineOptions.CodegenOptions)