88
99namespace BenchmarkDotNet . Engines
1010{
11- internal abstract class EngineJitStage ( int unrollFactor , EngineParameters parameters ) : EngineStage ( IterationStage . Jitting , IterationMode . Workload , parameters )
11+ internal abstract class EngineJitStage ( EngineParameters parameters ) : EngineStage ( IterationStage . Jitting , IterationMode . Workload , parameters )
1212 {
13- protected readonly int unrollFactor = unrollFactor ;
1413 protected readonly Action < long > dummy1Action = _ => parameters . Dummy1Action ( ) ;
1514 protected readonly Action < long > dummy2Action = _ => parameters . Dummy2Action ( ) ;
1615 protected readonly Action < long > dummy3Action = _ => parameters . Dummy3Action ( ) ;
@@ -24,26 +23,13 @@ internal sealed class EngineFirstJitStage : EngineJitStage
2423 // It is not worth spending a long time in jit stage for macro-benchmarks.
2524 private static readonly TimeInterval MaxTieringTime = TimeInterval . FromSeconds ( 10 ) ;
2625
27- internal bool didJitUnroll = false ;
2826 internal bool didStopEarly = false ;
2927 internal Measurement lastMeasurement ;
3028
31- private readonly Action < long > overheadAction ;
32- private readonly Action < long > workloadAction ;
3329 private readonly IEnumerator < IterationData > enumerator ;
3430
35- internal EngineFirstJitStage ( int unrollFactor , EngineParameters parameters ) : base ( unrollFactor , parameters )
31+ internal EngineFirstJitStage ( EngineParameters parameters ) : base ( parameters )
3632 {
37- if ( unrollFactor != 1 )
38- {
39- overheadAction = parameters . OverheadActionUnroll ;
40- workloadAction = parameters . WorkloadActionUnroll ;
41- }
42- else
43- {
44- overheadAction = parameters . OverheadActionNoUnroll ;
45- workloadAction = parameters . WorkloadActionNoUnroll ;
46- }
4733 enumerator = EnumerateIterations ( ) ;
4834 }
4935
@@ -88,9 +74,9 @@ private IEnumerator<IterationData> EnumerateIterations()
8874 {
8975 ++ iterationIndex ;
9076 yield return GetDummyIterationData ( dummy1Action ) ;
91- yield return GetOverheadNoUnrollIterationData ( ) ;
77+ yield return GetOverheadIterationData ( ) ;
9278 yield return GetDummyIterationData ( dummy2Action ) ;
93- yield return GetWorkloadNoUnrollIterationData ( ) ;
79+ yield return GetWorkloadIterationData ( ) ;
9480 yield return GetDummyIterationData ( dummy3Action ) ;
9581
9682 // If the jit is not tiered, we're done.
@@ -102,103 +88,33 @@ private IEnumerator<IterationData> EnumerateIterations()
10288 // Wait enough time for jit call counting to begin.
10389 MaybeSleep ( JitInfo . TieredDelay ) ;
10490
105- // If the jit is configured for aggressive tiering, ignore how long it takes, and run 1 set of iterations per jit tier to fully promote the methods to tier1.
106- if ( JitInfo . TieredCallCountThreshold == 1 )
107- {
108- ++ iterationIndex ;
109- yield return GetOverheadNoUnrollIterationData ( ) ;
110- yield return GetWorkloadNoUnrollIterationData ( ) ;
111-
112- MaybeSleep ( JitInfo . BackgroundCompilationDelay ) ;
113-
114- if ( JitInfo . IsDPGO )
115- {
116- ++ iterationIndex ;
117- yield return GetOverheadNoUnrollIterationData ( ) ;
118- yield return GetWorkloadNoUnrollIterationData ( ) ;
119- }
120-
121- MaybeSleep ( JitInfo . BackgroundCompilationDelay ) ;
122-
123- yield break ;
124- }
125-
126- // Otherwise, attempt to promote methods to tier1, but don't spend too much time in jit stage.
91+ // Attempt to promote methods to tier1, but don't spend too much time in jit stage.
12792 StartedClock startedClock = parameters . TargetJob . ResolveValue ( InfrastructureMode . ClockCharacteristic , parameters . Resolver ) . Start ( ) ;
12893
129- ++ iterationIndex ;
130- yield return GetOverheadNoUnrollIterationData ( ) ;
131- yield return GetWorkloadNoUnrollIterationData ( ) ;
132-
133- if ( startedClock . GetElapsed ( ) . GetTimeValue ( ) >= MaxTieringTime )
134- {
135- didStopEarly = true ;
136- yield break ;
137- }
138-
139- int tier0CallCount = JitInfo . TieredCallCountThreshold - 1 ;
140- // Run unroll method if it's not too many invocations.
141- if ( unrollFactor <= tier0CallCount )
142- {
143- tier0CallCount -= unrollFactor ;
144- ++ iterationIndex ;
145- yield return GetOverheadUnrollIterationData ( ) ;
146- yield return GetWorkloadUnrollIterationData ( ) ;
147-
148- didJitUnroll = unrollFactor != 1 ;
149-
150- if ( startedClock . GetElapsed ( ) . GetTimeValue ( ) >= MaxTieringTime )
151- {
152- didStopEarly = true ;
153- yield break ;
154- }
155- }
156-
157- // Run the remaining iterations without unroll.
158- for ( int i = 0 ; i < tier0CallCount ; ++ i )
159- {
160- ++ iterationIndex ;
161- yield return GetOverheadNoUnrollIterationData ( ) ;
162- yield return GetWorkloadNoUnrollIterationData ( ) ;
163-
164- if ( startedClock . GetElapsed ( ) . GetTimeValue ( ) >= MaxTieringTime )
165- {
166- didStopEarly = true ;
167- yield break ;
168- }
169- }
170-
171- MaybeSleep ( JitInfo . BackgroundCompilationDelay ) ;
172-
173- if ( JitInfo . IsDPGO )
94+ for ( int tierCount = JitInfo . IsDPGO ? 2 : 1 ; tierCount >= 0 ; -- tierCount )
17495 {
175- for ( int i = 0 ; i < JitInfo . TieredCallCountThreshold ; ++ i )
96+ for ( int callCount = JitInfo . TieredCallCountThreshold ; callCount >= 0 ; -- callCount )
17697 {
17798 ++ iterationIndex ;
178- yield return GetOverheadNoUnrollIterationData ( ) ;
179- yield return GetWorkloadNoUnrollIterationData ( ) ;
99+ yield return GetOverheadIterationData ( ) ;
100+ yield return GetWorkloadIterationData ( ) ;
180101
181- if ( startedClock . GetElapsed ( ) . GetTimeValue ( ) >= MaxTieringTime )
102+ if ( ( tierCount + callCount ) > 0
103+ && startedClock . GetElapsed ( ) . GetTimeValue ( ) >= MaxTieringTime )
182104 {
183105 didStopEarly = true ;
184106 yield break ;
185107 }
186108 }
187- }
188109
189- MaybeSleep ( JitInfo . BackgroundCompilationDelay ) ;
110+ MaybeSleep ( JitInfo . BackgroundCompilationDelay ) ;
111+ }
190112 }
191113
192- private IterationData GetOverheadUnrollIterationData ( )
193- => new ( IterationMode . Overhead , IterationStage . Jitting , iterationIndex , unrollFactor , unrollFactor , ( ) => { } , ( ) => { } , overheadAction ) ;
194-
195- private IterationData GetWorkloadUnrollIterationData ( )
196- => new ( IterationMode . Workload , IterationStage . Jitting , iterationIndex , unrollFactor , unrollFactor , parameters . IterationSetupAction , parameters . IterationCleanupAction , workloadAction ) ;
197-
198- private IterationData GetOverheadNoUnrollIterationData ( )
114+ private IterationData GetOverheadIterationData ( )
199115 => new ( IterationMode . Overhead , IterationStage . Jitting , iterationIndex , 1 , 1 , ( ) => { } , ( ) => { } , parameters . OverheadActionNoUnroll ) ;
200116
201- private IterationData GetWorkloadNoUnrollIterationData ( )
117+ private IterationData GetWorkloadIterationData ( )
202118 => new ( IterationMode . Workload , IterationStage . Jitting , iterationIndex , 1 , 1 , parameters . IterationSetupAction , parameters . IterationCleanupAction , parameters . WorkloadActionNoUnroll ) ;
203119
204120 private void MaybeSleep ( TimeSpan timeSpan )
@@ -210,8 +126,10 @@ private void MaybeSleep(TimeSpan timeSpan)
210126 }
211127 }
212128
213- internal sealed class EngineSecondJitStage ( int unrollFactor , EngineParameters parameters ) : EngineJitStage ( unrollFactor , parameters )
129+ internal sealed class EngineSecondJitStage ( int unrollFactor , EngineParameters parameters ) : EngineJitStage ( parameters )
214130 {
131+ private readonly int unrollFactor = unrollFactor ;
132+
215133 internal override List < Measurement > GetMeasurementList ( ) => new ( GetMaxCallCount ( ) ) ;
216134
217135 private static int GetMaxCallCount ( )
0 commit comments