diff --git a/src/BenchmarkDotNet.Core/Diagnosers/CompositeDiagnoser.cs b/src/BenchmarkDotNet.Core/Diagnosers/CompositeDiagnoser.cs index 29a954136..4fa59d88d 100644 --- a/src/BenchmarkDotNet.Core/Diagnosers/CompositeDiagnoser.cs +++ b/src/BenchmarkDotNet.Core/Diagnosers/CompositeDiagnoser.cs @@ -22,14 +22,14 @@ namespace BenchmarkDotNet.Diagnosers public IColumnProvider GetColumnProvider() => new CompositeColumnProvider(diagnosers.Select(d => d.GetColumnProvider()).ToArray()); - public void BeforeAnythingElse(Process process, Benchmark benchmark) - => diagnosers.ForEach(diagnoser => diagnoser.BeforeAnythingElse(process, benchmark)); + public void BeforeAnythingElse(DiagnoserActionParameters parameters) + => diagnosers.ForEach(diagnoser => diagnoser.BeforeAnythingElse(parameters)); - public void AfterSetup(Process process, Benchmark benchmark) - => diagnosers.ForEach(diagnoser => diagnoser.AfterSetup(process, benchmark)); + public void AfterSetup(DiagnoserActionParameters parameters) + => diagnosers.ForEach(diagnoser => diagnoser.AfterSetup(parameters)); - public void BeforeMainRun(Process process, Benchmark benchmark) - => diagnosers.ForEach(diagnoser => diagnoser.BeforeMainRun(process, benchmark)); + public void BeforeMainRun(DiagnoserActionParameters parameters) + => diagnosers.ForEach(diagnoser => diagnoser.BeforeMainRun(parameters)); public void BeforeCleanup() => diagnosers.ForEach(diagnoser => diagnoser.BeforeCleanup()); diff --git a/src/BenchmarkDotNet.Core/Diagnosers/DiagnoserActionParameters.cs b/src/BenchmarkDotNet.Core/Diagnosers/DiagnoserActionParameters.cs new file mode 100644 index 000000000..7d3fb7633 --- /dev/null +++ b/src/BenchmarkDotNet.Core/Diagnosers/DiagnoserActionParameters.cs @@ -0,0 +1,22 @@ +using System.Diagnostics; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Running; + +namespace BenchmarkDotNet.Diagnosers +{ + public class DiagnoserActionParameters + { + public DiagnoserActionParameters(Process process, Benchmark benchmark, IConfig config) + { + Process = process; + Benchmark = benchmark; + Config = config; + } + + public Process Process { get; } + + public Benchmark Benchmark { get; } + + public IConfig Config { get; } + } +} \ No newline at end of file diff --git a/src/BenchmarkDotNet.Core/Diagnosers/IDiagnoser.cs b/src/BenchmarkDotNet.Core/Diagnosers/IDiagnoser.cs index 7a92b6bee..ead834ca9 100644 --- a/src/BenchmarkDotNet.Core/Diagnosers/IDiagnoser.cs +++ b/src/BenchmarkDotNet.Core/Diagnosers/IDiagnoser.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Diagnostics; using BenchmarkDotNet.Columns; using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Running; @@ -15,17 +14,17 @@ namespace BenchmarkDotNet.Diagnosers /// /// before jitting, warmup /// - void BeforeAnythingElse(Process process, Benchmark benchmark); + void BeforeAnythingElse(DiagnoserActionParameters parameters); /// /// after setup, before run /// - void AfterSetup(Process process, Benchmark benchmark); + void AfterSetup(DiagnoserActionParameters parameters); /// /// after setup, warmup and pilot but before the main run /// - void BeforeMainRun(Process process, Benchmark benchmark); + void BeforeMainRun(DiagnoserActionParameters parameters); /// /// after run, before cleanup diff --git a/src/BenchmarkDotNet.Core/Diagnosers/MemoryDiagnoser.cs b/src/BenchmarkDotNet.Core/Diagnosers/MemoryDiagnoser.cs index 4461687fa..8caf9d46f 100644 --- a/src/BenchmarkDotNet.Core/Diagnosers/MemoryDiagnoser.cs +++ b/src/BenchmarkDotNet.Core/Diagnosers/MemoryDiagnoser.cs @@ -30,9 +30,9 @@ namespace BenchmarkDotNet.Diagnosers // the following methods are left empty on purpose // the action takes places in other process, and the values are gathered by Engine - public void BeforeAnythingElse(Process process, Benchmark benchmark) { } - public void AfterSetup(Process process, Benchmark benchmark) { } - public void BeforeMainRun(Process process, Benchmark benchmark) { } + public void BeforeAnythingElse(DiagnoserActionParameters _) { } + public void AfterSetup(DiagnoserActionParameters _) { } + public void BeforeMainRun(DiagnoserActionParameters _) { } public void BeforeCleanup() { } public void DisplayResults(ILogger logger) diff --git a/src/BenchmarkDotNet.Core/Loggers/NullLogger.cs b/src/BenchmarkDotNet.Core/Loggers/NullLogger.cs new file mode 100644 index 000000000..108610e40 --- /dev/null +++ b/src/BenchmarkDotNet.Core/Loggers/NullLogger.cs @@ -0,0 +1,15 @@ +namespace BenchmarkDotNet.Loggers +{ + public class NullLogger : ILogger + { + public static readonly ILogger Instance = new NullLogger(); + + private NullLogger() { } + + public void Write(LogKind logKind, string text) { } + + public void WriteLine() { } + + public void WriteLine(LogKind logKind, string text) { } + } +} \ No newline at end of file diff --git a/src/BenchmarkDotNet.Core/Loggers/SynchronousProcessOutputLoggerWithDiagnoser.cs b/src/BenchmarkDotNet.Core/Loggers/SynchronousProcessOutputLoggerWithDiagnoser.cs index fcfb48e30..d6e39d763 100644 --- a/src/BenchmarkDotNet.Core/Loggers/SynchronousProcessOutputLoggerWithDiagnoser.cs +++ b/src/BenchmarkDotNet.Core/Loggers/SynchronousProcessOutputLoggerWithDiagnoser.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; using BenchmarkDotNet.Engines; using BenchmarkDotNet.Running; @@ -13,8 +14,9 @@ namespace BenchmarkDotNet.Loggers private readonly Process process; private readonly Benchmark benchmark; private readonly IDiagnoser diagnoser; + private readonly DiagnoserActionParameters diagnoserActionParameters; - public SynchronousProcessOutputLoggerWithDiagnoser(ILogger logger, Process process, IDiagnoser diagnoser, Benchmark benchmark) + public SynchronousProcessOutputLoggerWithDiagnoser(ILogger logger, Process process, IDiagnoser diagnoser, Benchmark benchmark, IConfig config) { if (!process.StartInfo.RedirectStandardOutput) { @@ -25,6 +27,10 @@ namespace BenchmarkDotNet.Loggers this.process = process; this.diagnoser = diagnoser; this.benchmark = benchmark; + diagnoserActionParameters = new DiagnoserActionParameters( + process, + benchmark, + config); LinesWithResults = new List(); LinesWithExtraOutput = new List(); @@ -50,15 +56,15 @@ namespace BenchmarkDotNet.Loggers } else if (line == Engine.Signals.BeforeAnythingElse) { - diagnoser?.BeforeAnythingElse(process, benchmark); + diagnoser?.BeforeAnythingElse(diagnoserActionParameters); } else if (line == Engine.Signals.AfterSetup) { - diagnoser?.AfterSetup(process, benchmark); + diagnoser?.AfterSetup(diagnoserActionParameters); } else if (line == Engine.Signals.BeforeMainRun) { - diagnoser?.BeforeMainRun(process, benchmark); + diagnoser?.BeforeMainRun(diagnoserActionParameters); } else if (line == Engine.Signals.BeforeCleanup) { diff --git a/src/BenchmarkDotNet.Core/Running/BenchmarkRunnerCore.cs b/src/BenchmarkDotNet.Core/Running/BenchmarkRunnerCore.cs index 600377475..a136f77c8 100644 --- a/src/BenchmarkDotNet.Core/Running/BenchmarkRunnerCore.cs +++ b/src/BenchmarkDotNet.Core/Running/BenchmarkRunnerCore.cs @@ -15,6 +15,7 @@ using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Mathematics; using BenchmarkDotNet.Reports; using BenchmarkDotNet.Toolchains; +using BenchmarkDotNet.Toolchains.Parameters; using BenchmarkDotNet.Toolchains.Results; using BenchmarkDotNet.Validators; @@ -247,7 +248,8 @@ namespace BenchmarkDotNet.Running : " / " + launchCount; logger.WriteLineInfo($"// Launch: {launchIndex + 1}{printedLaunchCount}"); - var executeResult = toolchain.Executor.Execute(buildResult, benchmark, logger, resolver); + var executeResult = toolchain.Executor.Execute( + new ExecuteParameters(buildResult, benchmark, logger, resolver, config)); if (!executeResult.FoundExecutable) logger.WriteLineError($"Executable {buildResult.ArtifactsPaths.ExecutablePath} not found"); @@ -285,7 +287,8 @@ namespace BenchmarkDotNet.Running logger.WriteLineInfo("// Run, Diagnostic"); var compositeDiagnoser = config.GetCompositeDiagnoser(); - var executeResult = toolchain.Executor.Execute(buildResult, benchmark, logger, resolver, compositeDiagnoser); + var executeResult = toolchain.Executor.Execute( + new ExecuteParameters(buildResult, benchmark, logger, resolver, config, compositeDiagnoser)); var allRuns = executeResult.Data.Select(line => Measurement.Parse(logger, line, 0)).Where(r => r.IterationMode != IterationMode.Unknown).ToList(); gcStats = GcStats.Parse(executeResult.Data.Last()); diff --git a/src/BenchmarkDotNet.Core/Toolchains/DotNetCli/DotNetCliExecutor.cs b/src/BenchmarkDotNet.Core/Toolchains/DotNetCli/DotNetCliExecutor.cs index 80d0f6495..2245164fa 100644 --- a/src/BenchmarkDotNet.Core/Toolchains/DotNetCli/DotNetCliExecutor.cs +++ b/src/BenchmarkDotNet.Core/Toolchains/DotNetCli/DotNetCliExecutor.cs @@ -3,12 +3,14 @@ using System.Diagnostics; using System.IO; using System.Text; using BenchmarkDotNet.Characteristics; +using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; using BenchmarkDotNet.Engines; using BenchmarkDotNet.Extensions; using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Running; +using BenchmarkDotNet.Toolchains.Parameters; using BenchmarkDotNet.Toolchains.Results; using JetBrains.Annotations; @@ -17,23 +19,29 @@ namespace BenchmarkDotNet.Toolchains.DotNetCli [PublicAPI] public class DotNetCliExecutor : IExecutor { - public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser diagnoser = null) + public ExecuteResult Execute(ExecuteParameters executeParameters) { - var executableName = $"{buildResult.ArtifactsPaths.ProgramName}.dll"; - if (!File.Exists(Path.Combine(buildResult.ArtifactsPaths.BinariesDirectoryPath, executableName))) + var executableName = $"{executeParameters.BuildResult.ArtifactsPaths.ProgramName}.dll"; + if (!File.Exists(Path.Combine(executeParameters.BuildResult.ArtifactsPaths.BinariesDirectoryPath, executableName))) { - logger.WriteLineError($"Did not find {executableName} in {buildResult.ArtifactsPaths.BinariesDirectoryPath}, but the folder contained:"); - foreach (var file in new DirectoryInfo(buildResult.ArtifactsPaths.BinariesDirectoryPath).GetFiles("*.*")) - logger.WriteLineError(file.Name); + executeParameters.Logger.WriteLineError($"Did not find {executableName} in {executeParameters.BuildResult.ArtifactsPaths.BinariesDirectoryPath}, but the folder contained:"); + foreach (var file in new DirectoryInfo(executeParameters.BuildResult.ArtifactsPaths.BinariesDirectoryPath).GetFiles("*.*")) + executeParameters.Logger.WriteLineError(file.Name); return new ExecuteResult(false, -1, Array.Empty(), Array.Empty()); } - ConsoleHandler.EnsureInitialized(logger); + ConsoleHandler.EnsureInitialized(executeParameters.Logger); try { - return Execute(benchmark, logger, buildResult.ArtifactsPaths, diagnoser, executableName); + return Execute( + executeParameters.Benchmark, + executeParameters.Logger, + executeParameters.BuildResult.ArtifactsPaths, + executeParameters.Diagnoser, + executableName, + executeParameters.Config); } finally { @@ -41,7 +49,7 @@ namespace BenchmarkDotNet.Toolchains.DotNetCli } } - private ExecuteResult Execute(Benchmark benchmark, ILogger logger, ArtifactsPaths artifactsPaths, IDiagnoser diagnoser, string executableName) + private ExecuteResult Execute(Benchmark benchmark, ILogger logger, ArtifactsPaths artifactsPaths, IDiagnoser diagnoser, string executableName, IConfig config) { using (var process = new Process { @@ -50,7 +58,7 @@ namespace BenchmarkDotNet.Toolchains.DotNetCli BuildArgs(diagnoser, executableName)) }) { - var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark); + var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark, config); ConsoleHandler.Instance.SetProcess(process); diff --git a/src/BenchmarkDotNet.Core/Toolchains/Executor.cs b/src/BenchmarkDotNet.Core/Toolchains/Executor.cs index c9d2b6a8c..ae5f0b9d4 100644 --- a/src/BenchmarkDotNet.Core/Toolchains/Executor.cs +++ b/src/BenchmarkDotNet.Core/Toolchains/Executor.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using BenchmarkDotNet.Characteristics; +using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; using BenchmarkDotNet.Engines; using BenchmarkDotNet.Environments; @@ -12,6 +13,7 @@ using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Portability; using BenchmarkDotNet.Running; +using BenchmarkDotNet.Toolchains.Parameters; using BenchmarkDotNet.Toolchains.Results; using JetBrains.Annotations; @@ -20,21 +22,20 @@ namespace BenchmarkDotNet.Toolchains [PublicAPI("Used by some of our Superusers that implement their own Toolchains (e.g. Kestrel team)")] public class Executor : IExecutor { - public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser compositeDiagnoser = null) + public ExecuteResult Execute(ExecuteParameters executeParameters) { - var exePath = buildResult.ArtifactsPaths.ExecutablePath; - var args = compositeDiagnoser == null ? string.Empty : Engine.Signals.DiagnoserIsAttachedParam; + var exePath = executeParameters.BuildResult.ArtifactsPaths.ExecutablePath; + var args = executeParameters.Diagnoser == null ? string.Empty : Engine.Signals.DiagnoserIsAttachedParam; if (!File.Exists(exePath)) { return new ExecuteResult(false, -1, Array.Empty(), Array.Empty()); } - return Execute(benchmark, logger, exePath, null, args, compositeDiagnoser, resolver); + return Execute(executeParameters.Benchmark, executeParameters.Logger, exePath, null, args, executeParameters.Diagnoser, executeParameters.Resolver, executeParameters.Config); } - private ExecuteResult Execute(Benchmark benchmark, ILogger logger, string exePath, string workingDirectory, string args, IDiagnoser diagnoser, - IResolver resolver) + private ExecuteResult Execute(Benchmark benchmark, ILogger logger, string exePath, string workingDirectory, string args, IDiagnoser diagnoser, IResolver resolver, IConfig config) { ConsoleHandler.EnsureInitialized(logger); @@ -42,7 +43,7 @@ namespace BenchmarkDotNet.Toolchains { using (var process = new Process { StartInfo = CreateStartInfo(benchmark, exePath, args, workingDirectory, resolver) }) { - var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark); + var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark, config); return Execute(process, benchmark, loggerWithDiagnoser, logger); } diff --git a/src/BenchmarkDotNet.Core/Toolchains/IExecutor.cs b/src/BenchmarkDotNet.Core/Toolchains/IExecutor.cs index 4bbb3f761..85604ef36 100644 --- a/src/BenchmarkDotNet.Core/Toolchains/IExecutor.cs +++ b/src/BenchmarkDotNet.Core/Toolchains/IExecutor.cs @@ -1,13 +1,10 @@ -using BenchmarkDotNet.Characteristics; -using BenchmarkDotNet.Diagnosers; -using BenchmarkDotNet.Loggers; -using BenchmarkDotNet.Running; +using BenchmarkDotNet.Toolchains.Parameters; using BenchmarkDotNet.Toolchains.Results; namespace BenchmarkDotNet.Toolchains { public interface IExecutor { - ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser diagnoser = null); + ExecuteResult Execute(ExecuteParameters executeParameters); } } \ No newline at end of file diff --git a/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessExecutor.cs b/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessExecutor.cs index f45ed73a2..d61aaba39 100644 --- a/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessExecutor.cs +++ b/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessExecutor.cs @@ -13,6 +13,7 @@ using BenchmarkDotNet.Extensions; using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Running; +using BenchmarkDotNet.Toolchains.Parameters; using BenchmarkDotNet.Toolchains.Results; using JetBrains.Annotations; @@ -57,24 +58,17 @@ namespace BenchmarkDotNet.Toolchains.InProcess public bool LogOutput { get; } /// Executes the specified benchmark. - /// The build result. - /// The benchmark. - /// The logger. - /// The resolver. - /// The diagnoser. - /// Execution result. - public ExecuteResult Execute( - BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser diagnoser = null) + public ExecuteResult Execute(ExecuteParameters executeParameters) { // TODO: preallocate buffer for output (no direct logging)? - var hostLogger = LogOutput ? logger : new CompositeLogger(); - var host = new InProcessHost(benchmark, hostLogger, diagnoser); + var hostLogger = LogOutput ? executeParameters.Logger : NullLogger.Instance; + var host = new InProcessHost(executeParameters.Benchmark, hostLogger, executeParameters.Diagnoser, executeParameters.Config); int exitCode = -1; - var runThread = new Thread(() => exitCode = ExecuteCore(host, benchmark, logger)); + var runThread = new Thread(() => exitCode = ExecuteCore(host, executeParameters.Benchmark, executeParameters.Logger)); #if CLASSIC - if (benchmark.Target.Method.GetCustomAttributes(false).Any()) + if (executeParameters.Benchmark.Target.Method.GetCustomAttributes(false).Any()) { runThread.SetApartmentState(ApartmentState.STA); } @@ -87,10 +81,10 @@ namespace BenchmarkDotNet.Toolchains.InProcess if (!runThread.Join((int)timeout.TotalMilliseconds)) throw new InvalidOperationException( - $"Benchmark {benchmark.DisplayInfo} takes to long to run. " + + $"Benchmark {executeParameters.Benchmark.DisplayInfo} takes to long to run. " + "Prefer to use out-of-process toolchains for long-running benchmarks."); - return GetExecutionResult(host.RunResults, exitCode, logger); + return GetExecutionResult(host.RunResults, exitCode, executeParameters.Logger); } private int ExecuteCore(IHost host, Benchmark benchmark, ILogger logger) diff --git a/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessHost.cs b/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessHost.cs index ef37a7988..fe6d3a1d9 100644 --- a/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessHost.cs +++ b/src/BenchmarkDotNet.Core/Toolchains/InProcess/InProcessHost.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; using BenchmarkDotNet.Engines; using BenchmarkDotNet.Loggers; @@ -13,9 +14,6 @@ namespace BenchmarkDotNet.Toolchains.InProcess /// public sealed class InProcessHost : IHost { - [NotNull] - private readonly Benchmark benchmark; - [NotNull] private readonly ILogger logger; @@ -23,13 +21,13 @@ namespace BenchmarkDotNet.Toolchains.InProcess private readonly IDiagnoser diagnoser; [CanBeNull] - private readonly Process currentProcess; + private readonly DiagnoserActionParameters diagnoserActionParameters; /// Creates a new instance of . /// Current benchmark. /// Logger for informational output. /// Diagnosers, if attached. - public InProcessHost(Benchmark benchmark, ILogger logger, IDiagnoser diagnoser) + public InProcessHost(Benchmark benchmark, ILogger logger, IDiagnoser diagnoser, IConfig config) { if (benchmark == null) throw new ArgumentNullException(nameof(benchmark)); @@ -37,13 +35,15 @@ namespace BenchmarkDotNet.Toolchains.InProcess if (logger == null) throw new ArgumentNullException(nameof(logger)); - this.benchmark = benchmark; this.logger = logger; this.diagnoser = diagnoser; IsDiagnoserAttached = diagnoser != null; if (diagnoser != null) - currentProcess = Process.GetCurrentProcess(); + diagnoserActionParameters = new DiagnoserActionParameters( + Process.GetCurrentProcess(), + benchmark, + config); } /// True if there are diagnosers attached. @@ -72,15 +72,15 @@ namespace BenchmarkDotNet.Toolchains.InProcess switch (hostSignal) { case HostSignal.BeforeAnythingElse: - diagnoser?.BeforeAnythingElse(currentProcess, benchmark); + diagnoser?.BeforeAnythingElse(diagnoserActionParameters); WriteLine(Engine.Signals.BeforeAnythingElse); break; case HostSignal.AfterSetup: - diagnoser?.AfterSetup(currentProcess, benchmark); + diagnoser?.AfterSetup(diagnoserActionParameters); WriteLine(Engine.Signals.AfterSetup); break; case HostSignal.BeforeMainRun: - diagnoser?.BeforeMainRun(currentProcess, benchmark); + diagnoser?.BeforeMainRun(diagnoserActionParameters); WriteLine(Engine.Signals.BeforeMainRun); break; case HostSignal.BeforeCleanup: diff --git a/src/BenchmarkDotNet.Core/Toolchains/Parameters/ExecuteParameters.cs b/src/BenchmarkDotNet.Core/Toolchains/Parameters/ExecuteParameters.cs new file mode 100644 index 000000000..4be4e180e --- /dev/null +++ b/src/BenchmarkDotNet.Core/Toolchains/Parameters/ExecuteParameters.cs @@ -0,0 +1,34 @@ +using BenchmarkDotNet.Characteristics; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Loggers; +using BenchmarkDotNet.Running; +using BenchmarkDotNet.Toolchains.Results; + +namespace BenchmarkDotNet.Toolchains.Parameters +{ + public class ExecuteParameters + { + public ExecuteParameters(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IConfig config, IDiagnoser diagnoser = null) + { + BuildResult = buildResult; + Benchmark = benchmark; + Logger = logger; + Resolver = resolver; + Config = config; + Diagnoser = diagnoser; + } + + public BuildResult BuildResult { get; } + + public Benchmark Benchmark { get; } + + public ILogger Logger { get; } + + public IResolver Resolver { get; } + + public IConfig Config { get; } + + public IDiagnoser Diagnoser { get; } + } +} \ No newline at end of file diff --git a/src/BenchmarkDotNet.Diagnostics.Windows/EtwDiagnoser.cs b/src/BenchmarkDotNet.Diagnostics.Windows/EtwDiagnoser.cs index 234eb7ab5..013a0c85f 100644 --- a/src/BenchmarkDotNet.Diagnostics.Windows/EtwDiagnoser.cs +++ b/src/BenchmarkDotNet.Diagnostics.Windows/EtwDiagnoser.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using BenchmarkDotNet.Diagnosers; using Microsoft.Diagnostics.Tracing; using Microsoft.Diagnostics.Tracing.Parsers; using Microsoft.Diagnostics.Tracing.Session; @@ -24,18 +25,18 @@ namespace BenchmarkDotNet.Diagnostics.Windows protected abstract string SessionNamePrefix { get; } - protected void Start(Process process, Benchmark benchmark) + protected void Start(DiagnoserActionParameters parameters) { Cleanup(); - BenchmarkToProcess.Add(benchmark, process.Id); - StatsPerProcess.TryAdd(process.Id, GetInitializedStats(benchmark)); + BenchmarkToProcess.Add(parameters.Benchmark, parameters.Process.Id); + StatsPerProcess.TryAdd(parameters.Process.Id, GetInitializedStats(parameters)); - Session = CreateSession(benchmark); + Session = CreateSession(parameters.Benchmark); EnableProvider(); - AttachToEvents(Session, benchmark); + AttachToEvents(Session, parameters.Benchmark); // The ETW collection thread starts receiving events immediately, but we only // start aggregating them after ProcessStarted is called and we know which process @@ -49,7 +50,7 @@ namespace BenchmarkDotNet.Diagnostics.Windows WaitUntilStarted(task); } - protected virtual TStats GetInitializedStats(Benchmark benchmark) => new TStats(); + protected virtual TStats GetInitializedStats(DiagnoserActionParameters parameters) => new TStats(); protected virtual TraceEventSession CreateSession(Benchmark benchmark) => new TraceEventSession(GetSessionName(SessionNamePrefix, benchmark, benchmark.Parameters)); diff --git a/src/BenchmarkDotNet.Diagnostics.Windows/JitDiagnoser.cs b/src/BenchmarkDotNet.Diagnostics.Windows/JitDiagnoser.cs index 48288d7cf..8fae08df9 100644 --- a/src/BenchmarkDotNet.Diagnostics.Windows/JitDiagnoser.cs +++ b/src/BenchmarkDotNet.Diagnostics.Windows/JitDiagnoser.cs @@ -19,11 +19,11 @@ namespace BenchmarkDotNet.Diagnostics.Windows public IColumnProvider GetColumnProvider() => EmptyColumnProvider.Instance; - public void BeforeAnythingElse(Process process, Benchmark benchmark) => Start(process, benchmark); + public void BeforeAnythingElse(DiagnoserActionParameters parameters) => Start(parameters); - public void AfterSetup(Process process, Benchmark benchmark) { } + public void AfterSetup(DiagnoserActionParameters _) { } - public void BeforeMainRun(Process process, Benchmark benchmark) { } + public void BeforeMainRun(DiagnoserActionParameters _) { } public void BeforeCleanup() => Stop(); diff --git a/src/BenchmarkDotNet.Diagnostics.Windows/MemoryDiagnoser.cs b/src/BenchmarkDotNet.Diagnostics.Windows/MemoryDiagnoser.cs index b3eb6b80a..2023bd2af 100644 --- a/src/BenchmarkDotNet.Diagnostics.Windows/MemoryDiagnoser.cs +++ b/src/BenchmarkDotNet.Diagnostics.Windows/MemoryDiagnoser.cs @@ -30,11 +30,11 @@ namespace BenchmarkDotNet.Diagnostics.Windows protected override string SessionNamePrefix => "GC"; - public void BeforeAnythingElse(Process process, Benchmark benchmark) { } + public void BeforeAnythingElse(DiagnoserActionParameters _) { } - public void AfterSetup(Process process, Benchmark benchmark) { } + public void AfterSetup(DiagnoserActionParameters _) { } - public void BeforeMainRun(Process process, Benchmark benchmark) => Start(process, benchmark); + public void BeforeMainRun(DiagnoserActionParameters parameters) => Start(parameters); public void BeforeCleanup() => Stop(); diff --git a/src/BenchmarkDotNet.Diagnostics.Windows/PmcDiagnoser.cs b/src/BenchmarkDotNet.Diagnostics.Windows/PmcDiagnoser.cs index 7dc3ca444..da371905f 100644 --- a/src/BenchmarkDotNet.Diagnostics.Windows/PmcDiagnoser.cs +++ b/src/BenchmarkDotNet.Diagnostics.Windows/PmcDiagnoser.cs @@ -112,10 +112,10 @@ namespace BenchmarkDotNet.Diagnostics.Windows get { throw new NotImplementedException("Not needed for Kernel sessions (can be only one at a time"); } } - public void BeforeAnythingElse(Process process, Benchmark benchmark) { } - public void AfterSetup(Process process, Benchmark benchmark) { } + public void BeforeAnythingElse(DiagnoserActionParameters _) { } + public void AfterSetup(DiagnoserActionParameters _) { } - public void BeforeMainRun(Process process, Benchmark benchmark) => Start(process, benchmark); + public void BeforeMainRun(DiagnoserActionParameters parameters) => Start(parameters); public void BeforeCleanup() => Stop(); @@ -161,9 +161,9 @@ namespace BenchmarkDotNet.Diagnostics.Windows } } - protected override PmcStats GetInitializedStats(Benchmark benchmark) + protected override PmcStats GetInitializedStats(DiagnoserActionParameters parameters) { - var stats = new PmcStats(benchmark.Job.Diagnoser.HardwareCounters); + var stats = new PmcStats(parameters.Config.GetHardwareCounters().ToArray()); var counters = stats.Counters.Values; diff --git a/tests/BenchmarkDotNet.IntegrationTests/JobTests.cs b/tests/BenchmarkDotNet.IntegrationTests/JobTests.cs index e39a1fdad..cc7776e3c 100644 --- a/tests/BenchmarkDotNet.IntegrationTests/JobTests.cs +++ b/tests/BenchmarkDotNet.IntegrationTests/JobTests.cs @@ -371,12 +371,12 @@ namespace BenchmarkDotNet.IntegrationTests var a = CharacteristicHelper .GetThisTypeCharacteristics(typeof(Job)) .Select(c => c.Id); - Equal(string.Join(";", a), "Id;Accuracy;Diagnoser;Env;Infrastructure;Run"); + Equal(string.Join(";", a), "Id;Accuracy;Env;Infrastructure;Run"); a = CharacteristicHelper .GetAllCharacteristics(typeof(Job)) .Select(c => c.Id); Equal(string.Join(";", a), "Id;Accuracy;AnalyzeLaunchVariance;EvaluateOverhead;" + - "MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Diagnoser;HardwareCounters;Env;Affinity;" + + "MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Env;Affinity;" + "Jit;Platform;Runtime;Gc;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;" + "RetainVm;Server;Infrastructure;Clock;EngineFactory;Toolchain;Run;InvocationCount;IterationTime;" + "LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount"); diff --git a/tests/BenchmarkDotNet.IntegrationTests/ToolchainTest.cs b/tests/BenchmarkDotNet.IntegrationTests/ToolchainTest.cs index 180a8e554..49df783eb 100644 --- a/tests/BenchmarkDotNet.IntegrationTests/ToolchainTest.cs +++ b/tests/BenchmarkDotNet.IntegrationTests/ToolchainTest.cs @@ -8,6 +8,7 @@ using BenchmarkDotNet.Loggers; using BenchmarkDotNet.Running; using BenchmarkDotNet.Tests.Loggers; using BenchmarkDotNet.Toolchains; +using BenchmarkDotNet.Toolchains.Parameters; using BenchmarkDotNet.Toolchains.Results; using Xunit; using Xunit.Abstractions; @@ -46,9 +47,9 @@ namespace BenchmarkDotNet.IntegrationTests { public bool Done { get; private set; } - public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser diagnoser) + public ExecuteResult Execute(ExecuteParameters executeParameters) { - logger.WriteLine("Executing"); + executeParameters.Logger.WriteLine("Executing"); Done = true; return new ExecuteResult(true, 0, Array.Empty(), Array.Empty()); }