diff --git a/docs/articles/guides/how-it-works.md b/docs/articles/guides/how-it-works.md index 6b2bc0776c..da2402ea08 100644 --- a/docs/articles/guides/how-it-works.md +++ b/docs/articles/guides/how-it-works.md @@ -6,6 +6,7 @@ BenchmarkDotNet follows the following steps to run your benchmarks: 2. Next, we take each method/job/params combination and try to measure its performance by launching benchmark process several times (`LaunchCount`). 3. An invocation of the workload method is an *operation*. A bunch of operation is an *iteration*. If you have an `IterationSetup` method, it will be invoked before each iteration, but not between operations. We have the following type of iterations: + * `Jitting`: The overhead/workload methods are invoked to ensure they are JIT-compiled (and on tiered runtimes, to promote them when possible). These iterations are not used for measurements. * `Pilot`: The best operation count will be chosen. * `OverheadWarmup`, `OverheadWorkload`: BenchmarkDotNet overhead will be evaluated. * `ActualWarmup`: Warmup of the workload method. @@ -35,6 +36,7 @@ IEnumerable Run(Benchmark benchmark) Result ActualRun(Method method, Job job) { GlobalSetup(); + JittingStage(method); // triggers JIT compilation (and tiering if enabled) before Pilot/Warmup int unrollFactor = job.Run.UnrollFactor; // 16 by default @@ -54,6 +56,19 @@ Result ActualRun(Method method, Job job) return (result - Median(overhead), gcStats); } +void JittingStage(Method method) +{ + RunIteration(method, invokeCount: 1, unrollFactor: 1); + if (JitInfo.IsTiered) + { + for (int i = 0; i < JitInfo.MaxTierPromotions; i++) + { + RunIteration(method, invokeCount: JitInfo.TieredCallCountThreshold, unrollFactor: 1); + Thread.Sleep(250); + } + } +} + long Pilot(Method method, int unrollFactor) { // invokeCount is the equivalent of InnerIterationCount from xunit-performance