From 7de44dc93cbfbebfb847ff284b678254a1647883 Mon Sep 17 00:00:00 2001 From: filzrev <103790468+filzrev@users.noreply.github.com> Date: Sun, 27 Apr 2025 18:34:10 +0900 Subject: [PATCH] feat: add option to disable parallel build --- src/BenchmarkDotNet/Configs/ConfigOptions.cs | 6 +++- .../Running/BenchmarkRunnerClean.cs | 31 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/BenchmarkDotNet/Configs/ConfigOptions.cs b/src/BenchmarkDotNet/Configs/ConfigOptions.cs index c1ad75d642..06bc7768c7 100644 --- a/src/BenchmarkDotNet/Configs/ConfigOptions.cs +++ b/src/BenchmarkDotNet/Configs/ConfigOptions.cs @@ -48,7 +48,11 @@ public enum ConfigOptions /// /// Continue the execution if the last run was stopped. /// - Resume = 1 << 9 + Resume = 1 << 9, + /// + /// Determines whether parallel build of benchmark projects should be disabled. + /// + DisableParallelBuild = 1 << 10, } internal static class ConfigOptionsExtensions diff --git a/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs b/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs index 4f520da38d..12773880fc 100644 --- a/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs +++ b/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs @@ -88,7 +88,11 @@ internal static Summary[] Run(BenchmarkRunInfo[] benchmarkRunInfos) var buildPartitions = BenchmarkPartitioner.CreateForBuild(supportedBenchmarks, resolver); eventProcessor.OnStartBuildStage(buildPartitions); - var buildResults = BuildInParallel(compositeLogger, rootArtifactsFolderPath, buildPartitions, in globalChronometer, eventProcessor); + + bool useParallelBuild = !supportedBenchmarks.Any(x => x.Config.Options.IsSet(ConfigOptions.DisableParallelBuild)); + var buildResults = useParallelBuild + ? BuildInParallel(compositeLogger, rootArtifactsFolderPath, buildPartitions, in globalChronometer, eventProcessor) + : BuildSequential(compositeLogger, rootArtifactsFolderPath, buildPartitions, in globalChronometer, eventProcessor); var allBuildsHaveFailed = buildResults.Values.All(buildResult => !buildResult.IsBuildSuccess); @@ -413,6 +417,31 @@ static string GetFormattedDifference(ClockSpan before, ClockSpan after) => (after.GetTimeSpan() - before.GetTimeSpan()).ToFormattedTotalTime(DefaultCultureInfo.Instance); } + private static Dictionary BuildSequential(ILogger logger, string rootArtifactsFolderPath, BuildPartition[] buildPartitions, in StartedClock globalChronometer, EventProcessor eventProcessor) + { + logger.WriteLineHeader($"// ***** Building {buildPartitions.Length} exe(s): Start *****"); + + var buildLogger = buildPartitions.Length == 1 ? logger : NullLogger.Instance; // when we have just one partition we can print to std out + + var beforeBuild = globalChronometer.GetElapsed(); + + var buildResults = new Dictionary(); + foreach (var buildPartition in buildPartitions) + { + buildResults[buildPartition] = Build(buildPartition, rootArtifactsFolderPath, buildLogger); + eventProcessor.OnBuildComplete(buildPartition, buildResults[buildPartition]); + } + + var afterBuild = globalChronometer.GetElapsed(); + + logger.WriteLineHeader($"// ***** Done, took {GetFormattedDifference(beforeBuild, afterBuild)} *****"); + + return buildResults; + + static string GetFormattedDifference(ClockSpan before, ClockSpan after) + => (after.GetTimeSpan() - before.GetTimeSpan()).ToFormattedTotalTime(DefaultCultureInfo.Instance); + } + private static BuildResult Build(BuildPartition buildPartition, string rootArtifactsFolderPath, ILogger buildLogger) { var toolchain = buildPartition.RepresentativeBenchmarkCase.GetToolchain(); // it's guaranteed that all the benchmarks in single partition have same toolchain