Skip to content

Commit c1d8ac6

Browse files
committed
do the math right for unroll factor for JIT, #736
1 parent 343a603 commit c1d8ac6

File tree

2 files changed

+10
-9
lines changed

2 files changed

+10
-9
lines changed

src/BenchmarkDotNet/Engines/EngineFactory.cs

+6-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
2929
throw new ArgumentNullException(nameof(engineParameters.TargetJob));
3030

3131
var resolver = new CompositeResolver(BenchmarkRunner.DefaultResolver, EngineResolver.Instance);
32+
var unrollFactor = engineParameters.TargetJob.ResolveValue(RunMode.UnrollFactorCharacteristic, resolver);
3233

3334
engineParameters.GlobalSetupAction?.Invoke();
3435

@@ -45,7 +46,7 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
4546
var singleActionEngine = CreateEngine(engineParameters, resolver, engineParameters.TargetJob, engineParameters.IdleSingleAction, engineParameters.MainSingleAction);
4647

4748
var iterationTime = resolver.Resolve(engineParameters.TargetJob, RunMode.IterationTimeCharacteristic);
48-
if (ShouldExecuteOncePerIteration(Jit(singleActionEngine), iterationTime))
49+
if (ShouldExecuteOncePerIteration(Jit(singleActionEngine, unrollFactor: 1), iterationTime))
4950
{
5051
var reconfiguredJob = engineParameters.TargetJob.WithInvocationCount(1).WithUnrollFactor(1); // todo: consider if we should set the warmup count to 1!
5152

@@ -56,7 +57,7 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
5657
// it's either a job with explicit configuration or not-very time consuming benchmark, just create the engine, Jit and return
5758
var multiActionEngine = CreateEngine(engineParameters, resolver, engineParameters.TargetJob, engineParameters.IdleMultiAction, engineParameters.MainMultiAction);
5859

59-
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(multiActionEngine));
60+
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(multiActionEngine, unrollFactor));
6061

6162
return multiActionEngine;
6263
}
@@ -67,11 +68,11 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
6768
private static bool ShouldExecuteOncePerIteration(Measurement jit, TimeInterval iterationTime)
6869
=> TimeInterval.FromNanoseconds(jit.GetAverageNanoseconds()) > iterationTime;
6970

70-
private static Measurement Jit(Engine engine)
71+
private static Measurement Jit(Engine engine, int unrollFactor)
7172
{
72-
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(engine.RunIteration(new IterationData(IterationMode.IdleJit, index: -1, invokeCount: 1, unrollFactor: 1))); // don't forget to JIT idle
73+
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(engine.RunIteration(new IterationData(IterationMode.IdleJit, index: -1, invokeCount: unrollFactor, unrollFactor: unrollFactor))); // don't forget to JIT idle
7374

74-
return engine.RunIteration(new IterationData(IterationMode.Jit, index: -1, invokeCount: 1, unrollFactor: 1));
75+
return engine.RunIteration(new IterationData(IterationMode.Jit, index: -1, invokeCount: unrollFactor, unrollFactor: unrollFactor));
7576
}
7677

7778
private static Engine CreateEngine(EngineParameters engineParameters, IResolver resolver, Job job, Action<long> idle, Action<long> main)

tests/BenchmarkDotNet.Tests/Engine/EngineFactoryTests.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ public void VeryTimeConsumingBenchmarksAreExecutedOncePerIterationForDefaultSett
3939
var engine = new EngineFactory().CreateReadyToRun(engineParameters);
4040

4141
Assert.Equal(1, timesGlobalSetupCalled);
42-
Assert.Equal(1, timesIterationSetupCalled);
42+
Assert.Equal(1 + 1, timesIterationSetupCalled); // 1x for Idle, 1x for Target
4343
Assert.Equal(1, timesBenchmarkCalled);
4444
Assert.Equal(1, timesIdleCalled);
45-
Assert.Equal(1, timesIterationCleanupCalled);
45+
Assert.Equal(1 + 1, timesIterationCleanupCalled); // 1x for Idle, 1x for Target
4646
Assert.Equal(0, timesGlobalCleanupCalled); // cleanup is called as part of dispode
4747

4848
Assert.Equal(1, engine.TargetJob.Run.InvocationCount); // call the benchmark once per iteration
@@ -80,10 +80,10 @@ public void NonVeryTimeConsumingBenchmarksAreExecutedMoreThanOncePerIterationWit
8080
var engine = new EngineFactory().CreateReadyToRun(engineParameters);
8181

8282
Assert.Equal(1, timesGlobalSetupCalled);
83-
Assert.Equal(2, timesIterationSetupCalled); // once for single and & once for 16
83+
Assert.Equal((1+1) * (1+1), timesIterationSetupCalled); // (once for single and & once for 16) x (1x for Idle + 1x for Target)
8484
Assert.Equal(1 + 16, timesBenchmarkCalled);
8585
Assert.Equal(1 + 16, timesIdleCalled);
86-
Assert.Equal(2, timesIterationCleanupCalled); // once for single and & once for 16
86+
Assert.Equal((1+1) * (1+1), timesIterationCleanupCalled); // (once for single and & once for 16) x (1x for Idle + 1x for Target)
8787
Assert.Equal(0, timesGlobalCleanupCalled);
8888

8989
Assert.False(engine.TargetJob.Run.HasValue(RunMode.InvocationCountCharacteristic));

0 commit comments

Comments
 (0)