10000 Added missing ValueTask (non-generic) to InProcess (no emit) toolchains. · dotnet/BenchmarkDotNet@369133b · GitHub
[go: up one dir, main page]

Skip to content

Commit 369133b

Browse files
committed
Added missing ValueTask (non-generic) to InProcess (no emit) toolchains.
1 parent 5720494 commit 369133b

File tree

6 files changed

+359
-25
lines changed

6 files changed

+359
-25
lines changed

src/BenchmarkDotNet/Toolchains/InProcess.NoEmit/BenchmarkActionFactory.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ private static BenchmarkAction CreateCore(
3232
if (resultType == typeof(Task))
3333
return new BenchmarkActionTask(resultInstance, targetMethod, unrollFactor);
3434

35+
if (resultType == typeof(ValueTask))
36+
return new BenchmarkActionValueTask(resultInstance, targetMethod, unrollFactor);
37+
3538
if (resultType.GetTypeInfo().IsGenericType)
3639
{
3740
var genericType = resultType.GetGenericTypeDefinition();

src/BenchmarkDotNet/Toolchains/InProcess.NoEmit/BenchmarkActionFactory_Implementations.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,46 @@ private void InvokeMultipleHardcoded(long repeatCount)
150150
public override object LastRunResult => result;
151151
}
152152

153+
internal class BenchmarkActionValueTask : BenchmarkActionBase
154+
{
155+
private readonly Helpers.AwaitHelper awaitHelper = new Helpers.AwaitHelper();
156+
private readonly Func<ValueTask> startTaskCallback;
157+
private readonly Action callback;
158+
private readonly Action unrolledCallback;
159+
160+
public BenchmarkActionValueTask(object instance, MethodInfo method, int unrollFactor)
161+
{
162+
bool isIdle = method == null;
163+
if (!isIdle)
164+
{
165+
startTaskCallback = CreateWorkload<Func<ValueTask>>(instance, method);
166+
callback = ExecuteBlocking;
167+
}
168+
else
169+
{
170+
callback = Overhead;
171+
}
172+
173+
InvokeSingle = callback;
174+
175+
unrolledCallback = Unroll(callback, unrollFactor);
176+
InvokeMultiple = InvokeMultipleHardcoded;
177+
178+
}
179+
180+
// must be kept in sync with VoidDeclarationsProvider.IdleImplementation
181+
private void Overhead() { }
182+
183+
// must be kept in sync with TaskDeclarationsProvider.TargetMethodDelegate
184+
private void ExecuteBlocking() => awaitHelper.GetResult(startTaskCallback.Invoke());
185+
186+
private void InvokeMultipleHardcoded(long repeatCount)
187+
{
188+
for (long i = 0; i < repeatCount; i++)
189+
unrolledCallback();
190+
}
191+
}
192+
153193
internal class BenchmarkActionValueTask<T> : BenchmarkActionBase
154194
{
155195
private readonly Helpers.AwaitHelper awaitHelper = new Helpers.AwaitHelper();

src/BenchmarkDotNet/Toolchains/InProcess/BenchmarkActionFactory.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ private static BenchmarkAction CreateCore(
3434
if (resultType == typeof(Task))
3535
return new BenchmarkActionTask(resultInstance, targetMethod, codegenMode, unrollFactor);
3636

37+
if (resultType == typeof(ValueTask))
38+
return new BenchmarkActionValueTask(resultInstance, targetMethod, codegenMode, unrollFactor);
39+
3740
if (resultType.GetTypeInfo().IsGenericType)
3841
{
3942
var genericType = resultType.GetGenericTypeDefinition();

src/BenchmarkDotNet/Toolchains/InProcess/BenchmarkActionFactory_Implementations.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,52 @@ private void InvokeMultipleHardcoded(long repeatCount)
177177
public override object LastRunResult => result;
178178
}
179179

180+
internal class BenchmarkActionValueTask : BenchmarkActionBase
181+
{
182+
private readonly Helpers.AwaitHelper awaitHelper = new Helpers.AwaitHelper();
183+
private readonly Func<ValueTask> startTaskCallback;
184+
private readonly Action callback;
185+
private readonly Action unrolledCallback;
186+
187+
public BenchmarkActionValueTask(object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor)
188+
{
189+
bool isIdle = method == null;
190+
if (!isIdle)
191+
{
192+
startTaskCallback = CreateWorkload<Func<ValueTask>>(instance, method);
193+
callback = ExecuteBlocking;
194+
}
195+
else
196+
{
197+
callback = Overhead;
198+
}
199+
200+
InvokeSingle = callback;
201+
202+
if (UseFallbackCode(codegenMode, unrollFactor))
203+
{
204+
unrolledCallback = Unroll(callback, unrollFactor);
205+
InvokeMultiple = InvokeMultipleHardcoded;
206+
}
207+
else
208+
{
209+
InvokeMultiple = EmitInvokeMultiple(this, nameof(callback), null, unrollFactor);
210+
}
211+
}
212+
213+
// must be kept in sync with VoidDeclarationsProvider.IdleImplementation
214+
private void Overhead() { }
215+
216+
// must be kept in sync with TaskDeclarationsProvider.TargetMethodDelegate
217+
private void ExecuteBlocking() => awaitHelper.GetResult(startTaskCallback.Invoke());
218+
219+
private void InvokeMultipleHardcoded(long repeatCount)
220+
{
221+
for (long i = 0; i < repeatCount; i++)
222+
unrolledCallback();
223+
}
224+
}
225+
180226
internal class BenchmarkActionValueTask<T> : BenchmarkActionBase
181227
{
182228
private readonly Helpers.AwaitHelper awaitHelper = new Helpers.AwaitHelper();

tests/BenchmarkDotNet.IntegrationTests/AllSetupAndCleanupTest.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,5 +258,97 @@ public ValueTask<int> GlobalCleanup()
258258
[Benchmark]
259259
public void Benchmark() => Console.WriteLine(BenchmarkCalled);
260260
}
261+
262+
[Fact]
263+
public void AllSetupAndCleanupMethodRunsAsyncValueTaskBackByIValueTaskSourceSetupTest()
264+
{
265+
var miniJob = Job.Default.WithStrategy(RunStrategy.Monitoring).WithWarmupCount(2).WithIterationCount(3).WithInvocationCount(1).WithUnrollFactor(1).WithId("MiniJob");
266+
var config = CreateSimpleConfig(job: miniJob);
267+
268+
var summary = CanExecute<AllSetupAndCleanupAttributeBenchmarksAsyncValueTaskSetup>(config);
269+
270+
var actualLogLines = GetActualLogLines(summary);
271+
foreach (string line in actualLogLines)
272+
Output.WriteLine(line);
273+
Assert.Equal(expectedLogLines, actualLogLines);
274+
}
275+
276+
public class AllSetupAndCleanupAttributeBenchmarksAsyncValueTaskBackByIValueTaskSourceSetup
277+
{
278+
private readonly ValueTaskSource<int> valueTaskSource = new ();
279+
private int setupCounter;
280+
private int cleanupCounter;
281+
282+
[IterationSetup]
283+
public void IterationSetup() => Console.WriteLine(IterationSetupCalled + " (" + ++setupCounter + ")");
284+
285+
[IterationCleanup]
286+
public void IterationCleanup() => Console.WriteLine(IterationCleanupCalled + " (" + ++cleanupCounter + ")");
287+
288+
[GlobalSetup]
289+
public ValueTask GlobalSetup()
290+
{
291+
valueTaskSource.Reset();
292+
Console.Out.WriteLineAsync(GlobalSetupCalled).ContinueWith(_ => valueTaskSource.SetResult(42));
293+
return new ValueTask(valueTaskSource, valueTaskSource.Token);
294+
}
295+
296+
[GlobalCleanup]
297+
public ValueTask GlobalCleanup()
298+
{
299+
valueTaskSource.Reset();
300+
Console.Out.WriteLineAsync(GlobalCleanupCalled).ContinueWith(_ => valueTaskSource.SetResult(42));
301+
return new ValueTask(valueTaskSource, valueTaskSource.Token);
302+
}
303+
304+
[Benchmark]
305+
public void Benchmark() => Console.WriteLine(BenchmarkCalled);
306+
}
307+
308+
[FactNotGitHubActionsWindows]
309+
public void AllSetupAndCleanupMethodRunsAsyncGenericValueTaskBackByIValueTaskSourceSetupTest()
310+
{
311+
var miniJob = Job.Default.WithStrategy(RunStrategy.Monitoring).WithWarmupCount(2).WithIterationCount(3).WithInvocationCount(1).WithUnrollFactor(1).WithId("MiniJob");
312+
var config = CreateSimpleConfig(job: miniJob);
313+
314+
var summary = CanExecute<AllSetupAndCleanupAttributeBenchmarksAsyncGenericValueTaskSetup>(config);
315+
316+
var actualLogLines = GetActualLogLines(summary);
317+
foreach (string line in actualLogLines)
318+
Output.WriteLine(line);
319+
Assert.Equal(expectedLogLines, actualLogLines);
320+
}
321+
322+
public class AllSetupAndCleanupAttributeBenchmarksAsyncGenericValueTaskBackByIValueTaskSourceSetup
323+
{
324+
private readonly ValueTaskSource<int> valueTaskSource = new ();
325+
private int setupCounter;
326+
private int cleanupCounter;
327+
328+
[IterationSetup]
329+
public void IterationSetup() => Console.WriteLine(IterationSetupCalled + " (" + ++setupCounter + ")");
330+
331+
[IterationCleanup]
332+
public void IterationCleanup() => Console.WriteLine(IterationCleanupCalled + " (" + ++cleanupCounter + ")");
333+
334+
[GlobalSetup]
335+
public ValueTask<int> GlobalSetup()
336+
{
337+
valueTaskSource.Reset();
338+
Console.Out.WriteLineAsync(GlobalSetupCalled).ContinueWith(_ => valueTaskSource.SetResult(42));
339+
return new ValueTask<int>(valueTaskSource, valueTaskSource.Token);
340+
}
341+
342+
[GlobalCleanup]
343+
public ValueTask<int> GlobalCleanup()
344+
{
345+
valueTaskSource.Reset();
346+
Console.Out.WriteLineAsync(GlobalCleanupCalled).ContinueWith(_ => valueTaskSource.SetResult(42));
347+
return new ValueTask<int>(valueTaskSource, valueTaskSource.Token);
348+
}
349+
350+
[Benchmark]
351+
public void Benchmark() => Console.WriteLine(BenchmarkCalled);
352+
}
261353
}
262354
}

0 commit comments

Comments
 (0)
0