forked from dotnet/BenchmarkDotNet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
don't execute long operations more than once per iteration (dotnet#760)…
…, fixes dotnet#736 * don't execute long operations more than once per iteration, dotnet#736 * generate the right C# code for dotnet#736 * EngineParameters.Resolver was always null or ignored ;), dotnet#736 * don't forget to JIT idle, dotnet#736 * do the math right for unroll factor for JIT, dotnet#736 * generate the right IL code, dotnet#736 * Setup and Cleanup are jitted together with benchmark, dotnet#736 * engine factory is now supposed to create an engine which is ready to run (hence the method name change), dotnet#736 * addressing PR feedback, dotnet#736 * bring back the calls to DummyActions, dotnet#736 * align iteration mode * don't measure the overhead for time consuming benchmarks, don't run pilot if jitting gives the answer, dotnet#736 * fix the Linux build
- Loading branch information
1 parent
93e0302
commit f211c51
Showing
20 changed files
with
461 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,114 @@ | ||
using System; | ||
using BenchmarkDotNet.Horology; | ||
using BenchmarkDotNet.Jobs; | ||
using BenchmarkDotNet.Reports; | ||
using BenchmarkDotNet.Running; | ||
|
||
namespace BenchmarkDotNet.Engines | ||
{ | ||
// TODO: Default instance? | ||
public class EngineFactory : IEngineFactory | ||
{ | ||
public IEngine Create(EngineParameters engineParameters) | ||
public IEngine CreateReadyToRun(EngineParameters engineParameters) | ||
{ | ||
if (engineParameters.MainAction == null) | ||
throw new ArgumentNullException(nameof(engineParameters.MainAction)); | ||
if (engineParameters.MainSingleAction == null) | ||
throw new ArgumentNullException(nameof(engineParameters.MainSingleAction)); | ||
if (engineParameters.MainMultiAction == null) | ||
throw new ArgumentNullException(nameof(engineParameters.MainMultiAction)); | ||
if (engineParameters.Dummy1Action == null) | ||
throw new ArgumentNullException(nameof(engineParameters.Dummy1Action)); | ||
if (engineParameters.Dummy2Action == null) | ||
throw new ArgumentNullException(nameof(engineParameters.Dummy2Action)); | ||
if (engineParameters.Dummy3Action == null) | ||
throw new ArgumentNullException(nameof(engineParameters.Dummy3Action)); | ||
if (engineParameters.IdleAction == null) | ||
throw new ArgumentNullException(nameof(engineParameters.IdleAction)); | ||
if (engineParameters.IdleSingleAction == null) | ||
throw new ArgumentNullException(nameof(engineParameters.IdleSingleAction)); | ||
if (engineParameters.IdleMultiAction == null) | ||
throw new ArgumentNullException(nameof(engineParameters.IdleMultiAction)); | ||
if(engineParameters.TargetJob == null) | ||
throw new ArgumentNullException(nameof(engineParameters.TargetJob)); | ||
|
||
return new Engine( | ||
engineParameters.GlobalSetupAction?.Invoke(); // whatever the settings are, we MUST call global setup here, the global cleanup is part of Engine's Dispose | ||
|
||
if (!engineParameters.NeedsJitting) // just create the engine, do NOT jit | ||
return CreateMultiActionEngine(engineParameters); | ||
|
||
int jitIndex = 0; | ||
|
||
if (engineParameters.HasInvocationCount || engineParameters.HasUnrollFactor) // it's a job with explicit configuration, just create the engine and jit it | ||
{ | ||
var warmedUpMultiActionEngine = CreateMultiActionEngine(engineParameters); | ||
|
||
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(warmedUpMultiActionEngine, ++jitIndex, invokeCount: engineParameters.UnrollFactor, unrollFactor: engineParameters.UnrollFactor)); | ||
|
||
return warmedUpMultiActionEngine; | ||
} | ||
|
||
var singleActionEngine = CreateSingleActionEngine(engineParameters); | ||
if (Jit(singleActionEngine, ++jitIndex, invokeCount: 1, unrollFactor: 1) > engineParameters.IterationTime) | ||
return singleActionEngine; // executing once takes longer than iteration time => long running benchmark, needs no pilot and no overhead | ||
|
||
var multiActionEngine = CreateMultiActionEngine(engineParameters); | ||
int defaultUnrollFactor = Job.Default.ResolveValue(RunMode.UnrollFactorCharacteristic, EngineParameters.DefaultResolver); | ||
|
||
if (Jit(multiActionEngine, ++jitIndex, invokeCount: defaultUnrollFactor, unrollFactor: defaultUnrollFactor) > engineParameters.IterationTime) | ||
{ // executing defaultUnrollFactor times takes longer than iteration time => medium running benchmark, needs no pilot and no overhead | ||
var defaultUnrollFactorTimesPerIterationNoPilotNoOverhead = CreateJobWhichDoesNotNeedPilotAndOverheadEvaluation(engineParameters.TargetJob, | ||
invocationCount: defaultUnrollFactor, unrollFactor: defaultUnrollFactor); // run the benchmark exactly once per iteration | ||
|
||
return CreateEngine(engineParameters, defaultUnrollFactorTimesPerIterationNoPilotNoOverhead, engineParameters.IdleMultiAction, engineParameters.MainMultiAction); | ||
} | ||
|
||
return multiActionEngine; | ||
} | ||
|
||
/// <returns>the time it took to run the benchmark</returns> | ||
private static TimeInterval Jit(Engine engine, int jitIndex, int invokeCount, int unrollFactor) | ||
{ | ||
engine.Dummy1Action.Invoke(); | ||
|
||
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(engine.RunIteration(new IterationData(IterationMode.IdleJitting, jitIndex, invokeCount, unrollFactor))); // don't forget to JIT idle | ||
|
||
engine.Dummy2Action.Invoke(); | ||
|
||
var result = engine.RunIteration(new IterationData(IterationMode.MainJitting, jitIndex, invokeCount, unrollFactor)); | ||
|
||
engine.Dummy3Action.Invoke(); | ||
|
||
engine.WriteLine(); | ||
|
||
return TimeInterval.FromNanoseconds(result.Nanoseconds); | ||
} | ||
|
||
private static Engine CreateMultiActionEngine(EngineParameters engineParameters) | ||
=> CreateEngine(engineParameters, engineParameters.TargetJob, engineParameters.IdleMultiAction, engineParameters.MainMultiAction); | ||
|
||
private static Engine CreateSingleActionEngine(EngineParameters engineParameters) | ||
=> CreateEngine(engineParameters, | ||
CreateJobWhichDoesNotNeedPilotAndOverheadEvaluation(engineParameters.TargetJob, invocationCount: 1, unrollFactor: 1), // run the benchmark exactly once per iteration | ||
engineParameters.IdleSingleAction, | ||
engineParameters.MainSingleAction); | ||
|
||
private static Job CreateJobWhichDoesNotNeedPilotAndOverheadEvaluation(Job sourceJob, int invocationCount, int unrollFactor) | ||
=> sourceJob | ||
.WithInvocationCount(invocationCount).WithUnrollFactor(unrollFactor) | ||
.WithEvaluateOverhead(false); // it's very time consuming, don't evaluate the overhead which would be 0,000025% of the target run or even less | ||
// todo: consider if we should set the warmup count to 2 | ||
|
||
private static Engine CreateEngine(EngineParameters engineParameters, Job job, Action<long> idle, Action<long> main) | ||
=> new Engine( | ||
engineParameters.Host, | ||
EngineParameters.DefaultResolver, | ||
engineParameters.Dummy1Action, | ||
engineParameters.Dummy2Action, | ||
engineParameters.Dummy3Action, | ||
engineParameters.IdleAction, | ||
engineParameters.MainAction, | ||
engineParameters.TargetJob, | ||
idle, | ||
main, | ||
job, | ||
engineParameters.GlobalSetupAction, | ||
engineParameters.GlobalCleanupAction, | ||
engineParameters.IterationSetupAction, | ||
engineParameters.IterationCleanupAction, | ||
engineParameters.OperationsPerInvoke, | ||
engineParameters.MeasureGcStats); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,39 @@ | ||
using System; | ||
using BenchmarkDotNet.Characteristics; | ||
using BenchmarkDotNet.Horology; | ||
using BenchmarkDotNet.Jobs; | ||
using BenchmarkDotNet.Running; | ||
|
||
namespace BenchmarkDotNet.Engines | ||
{ | ||
public class EngineParameters | ||
{ | ||
public static readonly IResolver DefaultResolver = new CompositeResolver(BenchmarkRunner.DefaultResolver, EngineResolver.Instance); | ||
|
||
public IHost Host { get; set; } | ||
public Action<long> MainAction { get; set; } | ||
public Action<long> MainSingleAction { get; set; } | ||
public Action<long> MainMultiAction { get; set; } | ||
public Action Dummy1Action { get; set; } | ||
public Action Dummy2Action { get; set; } | ||
public Action Dummy3Action { get; set; } | ||
public Action<long> IdleAction { get; set; } | ||
public Action<long> IdleSingleAction { get; set; } | ||
public Action<long> IdleMultiAction { get; set; } | ||
public Job TargetJob { get; set; } = Job.Default; | ||
public long OperationsPerInvoke { get; set; } = 1; | ||
public Action GlobalSetupAction { get; set; } = null; | ||
public Action GlobalCleanupAction { get; set; } = null; | ||
public Action IterationSetupAction { get; set; } = null; | ||
public Action IterationCleanupAction { get; set; } = null; | ||
public IResolver Resolver { get; set; } | ||
public Action GlobalSetupAction { get; set; } | ||
public Action GlobalCleanupAction { get; set; } | ||
public Action IterationSetupAction { get; set; } | ||
public Action IterationCleanupAction { get; set; } | ||
public bool MeasureGcStats { get; set; } | ||
|
||
public bool NeedsJitting => TargetJob.ResolveValue(RunMode.RunStrategyCharacteristic, DefaultResolver).NeedsJitting(); | ||
|
||
public bool HasInvocationCount => TargetJob.HasValue(RunMode.InvocationCountCharacteristic); | ||
|
||
public bool HasUnrollFactor => TargetJob.HasValue(RunMode.UnrollFactorCharacteristic); | ||
|
||
public int UnrollFactor => TargetJob.ResolveValue(RunMode.UnrollFactorCharacteristic, DefaultResolver); | ||
|
||
public TimeInterval IterationTime => TargetJob.ResolveValue(RunMode.IterationTimeCharacteristic, DefaultResolver); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.