1
1
using System ;
2
+ using BenchmarkDotNet . Horology ;
3
+ using BenchmarkDotNet . Jobs ;
4
+ using BenchmarkDotNet . Reports ;
2
5
3
6
namespace BenchmarkDotNet . Engines
4
7
{
5
- // TODO: Default instance?
6
8
public class EngineFactory : IEngineFactory
7
9
{
8
- public IEngine Create ( EngineParameters engineParameters )
10
+ public IEngine CreateReadyToRun ( EngineParameters engineParameters )
9
11
{
10
- if ( engineParameters . MainAction == null )
11
- throw new ArgumentNullException ( nameof ( engineParameters . MainAction ) ) ;
12
+ if ( engineParameters . MainSingleAction == null )
13
+ throw new ArgumentNullException ( nameof ( engineParameters . MainSingleAction ) ) ;
14
+ if ( engineParameters . MainMultiAction == null )
15
+ throw new ArgumentNullException ( nameof ( engineParameters . MainMultiAction ) ) ;
12
16
if ( engineParameters . Dummy1Action == null )
13
17
throw new ArgumentNullException ( nameof ( engineParameters . Dummy1Action ) ) ;
14
18
if ( engineParameters . Dummy2Action == null )
15
19
throw new ArgumentNullException ( nameof ( engineParameters . Dummy2Action ) ) ;
16
20
if ( engineParameters . Dummy3Action == null )
17
21
throw new ArgumentNullException ( nameof ( engineParameters . Dummy3Action ) ) ;
18
- if ( engineParameters . IdleAction == null )
19
- throw new ArgumentNullException ( nameof ( engineParameters . IdleAction ) ) ;
22
+ if ( engineParameters . IdleSingleAction == null )
23
+ throw new ArgumentNullException ( nameof ( engineParameters . IdleSingleAction ) ) ;
24
+ if ( engineParameters . IdleMultiAction == null )
25
+ throw new ArgumentNullException ( nameof ( engineParameters . IdleMultiAction ) ) ;
20
26
if ( engineParameters . TargetJob == null )
21
27
throw new ArgumentNullException ( nameof ( engineParameters . TargetJob ) ) ;
28
+
29
+ engineParameters . GlobalSetupAction ? . Invoke ( ) ;
22
30
23
- return new Engine (
31
+ var needsJitting = engineParameters . TargetJob . ResolveValue ( RunMode . RunStrategyCharacteristic , engineParameters . Resolver ) . NeedsJitting ( ) ;
32
+ if ( ! needsJitting )
33
+ {
34
+ // whatever it is, we can not interfere
35
+ return CreateEngine ( engineParameters , engineParameters . TargetJob , engineParameters . IdleMultiAction , engineParameters . MainMultiAction ) ;
36
+ }
37
+
38
+ var needsPilot = ! engineParameters . TargetJob . HasValue ( RunMode . InvocationCountCharacteristic ) ;
39
+ if ( needsPilot )
40
+ {
41
+ var singleActionEngine = CreateEngine ( engineParameters , engineParameters . TargetJob , engineParameters . IdleSingleAction , engineParameters . MainSingleAction ) ;
42
+
43
+ var iterationTime = engineParameters . Resolver . Resolve ( engineParameters . TargetJob , RunMode . IterationTimeCharacteristic ) ;
44
+ if ( ShouldExecuteOncePerIteration ( Jit ( singleActionEngine ) , iterationTime ) )
45
+ {
46
+ var reconfiguredJob = engineParameters . TargetJob . WithInvocationCount ( 1 ) . WithUnrollFactor ( 1 ) ; // todo: consider if we should set the warmup count to 1!
47
+
48
+ return CreateEngine ( engineParameters , reconfiguredJob , engineParameters . IdleSingleAction , engineParameters . MainSingleAction ) ;
49
+ }
50
+ }
51
+
52
+ // it's either a job with explicit configuration or not-very time consuming benchmark, just create the engine, Jit and return
53
+ var multiActionEngine = CreateEngine ( engineParameters , engineParameters . TargetJob , engineParameters . IdleMultiAction , engineParameters . MainMultiAction ) ;
54
+
55
+ DeadCodeEliminationHelper . KeepAliveWithoutBoxing ( Jit ( multiActionEngine ) ) ;
56
+
57
+ return multiActionEngine ;
58
+ }
59
+
60
+ /// <summary>
61
+ /// returns true if it takes longer than the desired iteration time (0,5s by default) to execute benchmark once
62
+ /// </summary>
63
+ private static bool ShouldExecuteOncePerIteration ( Measurement jit , TimeInterval iterationTime )
64
+ => TimeInterval . FromNanoseconds ( jit . GetAverageNanoseconds ( ) ) > iterationTime ;
65
+
66
+ private static Measurement Jit ( Engine engine )
67
+ => engine . RunIteration ( new IterationData ( IterationMode . Jit , index : - 1 , invokeCount : 1 , unrollFactor : 1 ) ) ;
68
+
69
+ private static Engine CreateEngine ( EngineParameters engineParameters , Job job , Action < long > idle , Action < long > main )
70
+ => new Engine (
24
71
engineParameters . Host ,
25
72
engineParameters . Dummy1Action ,
26
73
engineParameters . Dummy2Action ,
27
74
engineParameters . Dummy3Action ,
28
- engineParameters . IdleAction ,
29
- engineParameters . MainAction ,
30
- engineParameters . TargetJob ,
75
+ idle ,
76
+ main ,
77
+ job ,
31
78
engineParameters . GlobalSetupAction ,
32
79
engineParameters . GlobalCleanupAction ,
33
80
engineParameters . IterationSetupAction ,
34
81
engineParameters . IterationCleanupAction ,
35
82
engineParameters . OperationsPerInvoke ,
36
83
engineParameters . MeasureGcStats ) ;
37
- }
38
84
}
39
85
}
0 commit comments