Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GenerateAndBuildOnly Option #2225

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/articles/configs/configoptions.md
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ The config options let you customize some behavior of BenchmarkDotNet - mainly r
Available config options are:

* `ConfigOptions.Default` - No configuration option is set - this is the default.
* `ConfigOptions.GenerateAndBuildOnly` - Only run toolchain generator and builder without executor. Then performs normal cleanup.
* `ConfigOptions.KeepBenchmarkFiles` - All auto-generated files should be kept after running the benchmarks (by default they are removed).
* `ConfigOptions.JoinSummary` - All benchmarks results should be joined into a single summary (by default we have a summary per type).
* `ConfigOptions.StopOnFirstError` - Benchmarking should be stopped after the first error (by default it's not).
21 changes: 21 additions & 0 deletions src/BenchmarkDotNet/Attributes/GenerateAndBuildOnlyAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using BenchmarkDotNet.Configs;
using JetBrains.Annotations;

namespace BenchmarkDotNet.Attributes
{
/// <summary>
/// determines if benchmark should be run after being generated and built
/// </summary>
[PublicAPI]
[AttributeUsage(AttributeTargets.Class)]
public class GenerateAndBuildOnlyAttribute : Attribute, IConfigSource
{
public IConfig Config { get; }

public GenerateAndBuildOnlyAttribute(bool value = true)
{
Config = ManualConfig.CreateEmpty().WithOption(ConfigOptions.GenerateAndBuildOnly, value);
}
}
}
5 changes: 5 additions & 0 deletions src/BenchmarkDotNet/Configs/ConfigExtensions.cs
Original file line number Diff line number Diff line change
@@ -80,6 +80,11 @@ public static class ConfigExtensions
/// </summary>
[PublicAPI] public static IConfig KeepBenchmarkFiles(this IConfig config, bool value = true) => config.WithOption(ConfigOptions.KeepBenchmarkFiles, value);

/// <summary>
/// determines if we skip executing after running generator and builder
/// </summary>
[PublicAPI] public static IConfig GenerateAndBuildOnly(this IConfig config, bool value = true) => config.WithOption(ConfigOptions.GenerateAndBuildOnly, value);

/// <summary>
/// determines if the exported result files should not be overwritten (be default they are overwritten)
/// </summary>
6 changes: 5 additions & 1 deletion src/BenchmarkDotNet/Configs/ConfigOptions.cs
Original file line number Diff line number Diff line change
@@ -48,7 +48,11 @@ public enum ConfigOptions
/// <summary>
/// Continue the execution if the last run was stopped.
/// </summary>
Resume = 1 << 9
Resume = 1 << 9,
/// <summary>
/// Don't run the benchmark after it's generated and built.
/// </summary>
GenerateAndBuildOnly = 1 << 10
}

internal static class ConfigOptionsExtensions
3 changes: 3 additions & 0 deletions src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs
Original file line number Diff line number Diff line change
@@ -86,6 +86,9 @@ public bool UseDisassemblyDiagnoser
[Option("keepFiles", Required = false, Default = false, HelpText = "Determines if all auto-generated files should be kept or removed after running the benchmarks.")]
public bool KeepBenchmarkFiles { get; set; }

[Option("generateAndBuildOnly", Required = false, Default = false, HelpText = "Determines if we only run generator and builder without executor.")]
public bool GenerateAndBuildOnly { get; set; }

[Option("noOverwrite", Required = false, Default = false, HelpText = "Determines if the exported result files should not be overwritten (be default they are overwritten).")]
public bool DontOverwriteResults { get; set; }

1 change: 1 addition & 0 deletions src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs
Original file line number Diff line number Diff line change
@@ -242,6 +242,7 @@ private static IConfig CreateConfig(CommandLineOptions options, IConfig globalCo

config.WithOption(ConfigOptions.JoinSummary, options.Join);
config.WithOption(ConfigOptions.KeepBenchmarkFiles, options.KeepBenchmarkFiles);
config.WithOption(ConfigOptions.GenerateAndBuildOnly, options.GenerateAndBuildOnly);
config.WithOption(ConfigOptions.DontOverwriteResults, options.DontOverwriteResults);
config.WithOption(ConfigOptions.StopOnFirstError, options.StopOnFirstError);
config.WithOption(ConfigOptions.DisableLogFile, options.DisableLogFile);
10 changes: 10 additions & 0 deletions src/BenchmarkDotNet/Reports/BenchmarkReport.cs
Original file line number Diff line number Diff line change
@@ -47,6 +47,16 @@ public BenchmarkReport(
?? (IReadOnlyDictionary<string, Metric>)ImmutableDictionary<string, Metric>.Empty;
}

internal BenchmarkReport(BenchmarkCase benchmarkCase, GenerateResult generateResult, BuildResult buildResult)
{
BenchmarkCase = benchmarkCase;
GenerateResult = generateResult;
BuildResult = buildResult;
ExecuteResults = Array.Empty<ExecuteResult>();
AllMeasurements = ImmutableList<Measurement>.Empty;
Metrics = ImmutableDictionary<string, Metric>.Empty;
}

public override string ToString() => $"{BenchmarkCase.DisplayInfo}, {AllMeasurements.Count} runs";

public IReadOnlyList<Measurement> GetResultRuns() => AllMeasurements.Where(r => r.Is(IterationMode.Workload, IterationStage.Result)).ToList();
10 changes: 9 additions & 1 deletion src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs
Original file line number Diff line number Diff line change
@@ -196,7 +196,15 @@ private static Summary Run(BenchmarkRunInfo benchmarkRunInfo,
if (!config.Options.IsSet(ConfigOptions.KeepBenchmarkFiles))
artifactsToCleanup.AddRange(buildResult.ArtifactsToCleanup);

var report = RunCore(benchmark, info.benchmarkId, logger, resolver, buildResult);
BenchmarkReport report;
if (config.Options.IsSet(ConfigOptions.GenerateAndBuildOnly))
{
report = new BenchmarkReport(benchmark, buildResult, buildResult);
reports.Add(report);
continue;
}

report = RunCore(benchmark, info.benchmarkId, logger, resolver, buildResult);
if (report.AllMeasurements.Any(m => m.Operations == 0))
throw new InvalidOperationException("An iteration with 'Operations == 0' detected");
reports.Add(report);