From e8378eccb3c274971528f689e59a51bb073dd824 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Thu, 17 Mar 2022 11:11:53 -0700 Subject: [PATCH] Revise heuristic for initial jitting. Increase the magic limit to 10s per #1780. Also use the "1.5" criteria for retry so we don't have odd threshold where initial jitting is a bit faster than IterationTime but not fast enough to trigger the multi action engine. --- src/BenchmarkDotNet/Engines/EngineFactory.cs | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/BenchmarkDotNet/Engines/EngineFactory.cs b/src/BenchmarkDotNet/Engines/EngineFactory.cs index c438890e84..0588218522 100644 --- a/src/BenchmarkDotNet/Engines/EngineFactory.cs +++ b/src/BenchmarkDotNet/Engines/EngineFactory.cs @@ -43,25 +43,23 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters) var singleActionEngine = CreateSingleActionEngine(engineParameters); var singleInvocationTime = Jit(singleActionEngine, ++jitIndex, invokeCount: 1, unrollFactor: 1); + double timesPerIteration = engineParameters.IterationTime / singleInvocationTime; // how many times can we run given benchmark per iteration - if (singleInvocationTime > engineParameters.IterationTime && singleInvocationTime < TimeInterval.FromSeconds(1.0)) + if ((timesPerIteration < 1.5) && (singleInvocationTime < TimeInterval.FromSeconds(10.0))) { - // if the Jitting took more than IterationTime but still less than 1s (a magic number based on observations of the reported bug) + // if the Jitting took more than IterationTime/1.5 but still less than 10s (a magic number based on observations of reported bugs) // we call it one more time to see if Jitting itself has not dominated the first invocation - // if it did, it shoud NOT be a single invocation engine (see #837, #1337 and #1338) + // if it did, it should NOT be a single invocation engine (see #837, #1337, #1338, and #1780) singleInvocationTime = Jit(singleActionEngine, ++jitIndex, invokeCount: 1, unrollFactor: 1); + timesPerIteration = engineParameters.IterationTime / singleInvocationTime; } - if (singleInvocationTime > engineParameters.IterationTime) - return singleActionEngine; // executing once takes longer than iteration time => long running benchmark, needs no pilot and no overhead - - int defaultUnrollFactor = Job.Default.ResolveValue(RunMode.UnrollFactorCharacteristic, EngineParameters.DefaultResolver); - - double timesPerIteration = engineParameters.IterationTime / singleInvocationTime; // how many times can we run given benchmark per iteration - - if (timesPerIteration < 1.5) // example: IterationTime is 0.5s, but single invocation takes 0.4s => we don't want to run it twice per iteration + // executing once takes longer than iteration time => long running benchmark, needs no pilot and no overhead + // Or executing twice would put us well past the iteration time ==> needs no pilot and no overhead + if (timesPerIteration < 1.5) return singleActionEngine; + int defaultUnrollFactor = Job.Default.ResolveValue(RunMode.UnrollFactorCharacteristic, EngineParameters.DefaultResolver); int roundedUpTimesPerIteration = (int)Math.Ceiling(timesPerIteration); if (roundedUpTimesPerIteration < defaultUnrollFactor) // if we run it defaultUnrollFactor times per iteration, it's going to take longer than IterationTime @@ -129,4 +127,4 @@ private static Engine CreateEngine(EngineParameters engineParameters, Job job, A engineParameters.MeasureExtraStats, engineParameters.BenchmarkName); } -} \ No newline at end of file +}