|
4 | 4 | using System.Reflection; |
5 | 5 | using System.Threading; |
6 | 6 | using BenchmarkDotNet.Detectors; |
7 | | -using BenchmarkDotNet.Diagnosers; |
8 | 7 | using BenchmarkDotNet.Engines; |
9 | | -using BenchmarkDotNet.Environments; |
10 | 8 | using BenchmarkDotNet.Extensions; |
11 | 9 | using BenchmarkDotNet.Jobs; |
12 | 10 | using BenchmarkDotNet.Loggers; |
|
16 | 14 |
|
17 | 15 | namespace BenchmarkDotNet.Toolchains.InProcess.Emit |
18 | 16 | { |
19 | | - /// <summary> |
20 | | - /// Implementation of <see cref="IExecutor" /> for in-process benchmarks. |
21 | | - /// </summary> |
22 | | - public class InProcessEmitExecutor : IExecutor |
| 17 | + internal class InProcessEmitExecutor(bool executeOnSeparateThread) : IExecutor |
23 | 18 | { |
24 | | - private static readonly TimeSpan UnderDebuggerTimeout = TimeSpan.FromDays(1); |
25 | | - private static readonly TimeSpan UnderProfilerTimeout = TimeSpan.FromDays(1); |
26 | | - |
27 | | - /// <summary> Default timeout for in-process benchmarks. </summary> |
28 | | - public static readonly TimeSpan DefaultTimeout = TimeSpan.FromMinutes(5); |
29 | | - |
30 | | - /// <summary>Initializes a new instance of the <see cref="InProcessEmitExecutor" /> class.</summary> |
31 | | - /// <param name="timeout">Timeout for the run.</param> |
32 | | - /// <param name="logOutput"><c>true</c> if the output should be logged.</param> |
33 | | - public InProcessEmitExecutor(TimeSpan timeout, bool logOutput) |
34 | | - { |
35 | | - if (timeout == TimeSpan.Zero) |
36 | | - timeout = DefaultTimeout; |
37 | | - |
38 | | - ExecutionTimeout = timeout; |
39 | | - LogOutput = logOutput; |
40 | | - } |
41 | | - |
42 | | - /// <summary>Timeout for the run.</summary> |
43 | | - /// <value>The timeout for the run.</value> |
44 | | - public TimeSpan ExecutionTimeout { get; } |
45 | | - |
46 | | - /// <summary>Gets a value indicating whether the output should be logged.</summary> |
47 | | - /// <value><c>true</c> if the output should be logged; otherwise, <c>false</c>.</value> |
48 | | - public bool LogOutput { get; } |
49 | | - |
50 | | - /// <summary>Executes the specified benchmark.</summary> |
51 | 19 | public ExecuteResult Execute(ExecuteParameters executeParameters) |
52 | 20 | { |
53 | | - // TODO: preallocate buffer for output (no direct logging)? |
54 | | - var hostLogger = LogOutput ? executeParameters.Logger : NullLogger.Instance; |
55 | | - var host = new InProcessHost(executeParameters.BenchmarkCase, hostLogger, executeParameters.Diagnoser); |
| 21 | + var host = new InProcessHost(executeParameters.BenchmarkCase, executeParameters.Logger, executeParameters.Diagnoser); |
56 | 22 |
|
57 | 23 | int exitCode = -1; |
58 | | - var runThread = new Thread(() => exitCode = ExecuteCore(host, executeParameters)); |
59 | | - |
60 | | - if (executeParameters.BenchmarkCase.Descriptor.WorkloadMethod |
61 | | - .GetCustomAttributes<STAThreadAttribute>(false) |
62 | | - .Any() && |
63 | | - OsDetector.IsWindows()) |
| 24 | + if (executeOnSeparateThread) |
64 | 25 | { |
65 | | - runThread.SetApartmentState(ApartmentState.STA); |
66 | | - } |
| 26 | + var runThread = new Thread(() => exitCode = ExecuteCore(host, executeParameters)); |
67 | 27 |
|
68 | | - runThread.IsBackground = true; |
69 | | - |
70 | | - var timeout = GetTimeout(executeParameters); |
71 | | - |
72 | | - runThread.Start(); |
| 28 | + if (executeParameters.BenchmarkCase.Descriptor.WorkloadMethod.GetCustomAttributes<STAThreadAttribute>(false).Any() |
| 29 | + && OsDetector.IsWindows()) |
| 30 | + { |
| 31 | + runThread.SetApartmentState(ApartmentState.STA); |
| 32 | + } |
73 | 33 |
|
74 | | - if (!runThread.Join((int)timeout.TotalMilliseconds)) |
75 | | - throw new InvalidOperationException( |
76 | | - $"Benchmark {executeParameters.BenchmarkCase.DisplayInfo} takes too long to run. " + |
77 | | - "Prefer to use out-of-process toolchains for long-running benchmarks."); |
| 34 | + runThread.IsBackground = true; |
78 | 35 |
|
| 36 | + runThread.Start(); |
| 37 | + runThread.Join(); |
| 38 | + } |
| 39 | + else |
| 40 | + { |
| 41 | + exitCode = ExecuteCore(host, executeParameters); |
| 42 | + } |
79 | 43 | host.HandleInProcessDiagnoserResults(executeParameters.BenchmarkCase, executeParameters.CompositeInProcessDiagnoser); |
80 | 44 |
|
81 | 45 | return ExecuteResult.FromRunResults(host.RunResults, exitCode); |
82 | 46 | } |
83 | 47 |
|
84 | | - private TimeSpan GetTimeout(ExecuteParameters executeParameters) |
85 | | - { |
86 | | - if (HostEnvironmentInfo.GetCurrent().HasAttachedDebugger) |
87 | | - return UnderDebuggerTimeout; |
88 | | - if (executeParameters.Diagnoser is IProfiler) |
89 | | - return UnderProfilerTimeout; |
90 | | - return ExecutionTimeout; |
91 | | - } |
92 | | - |
93 | 48 | private int ExecuteCore(IHost host, ExecuteParameters parameters) |
94 | 49 | { |
95 | 50 | int exitCode = -1; |
|
0 commit comments