Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create benchmarks for System.Threading.Tasks.Dataflow #951

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add ActionBlock Dataflow perf tests
  • Loading branch information
manandre committed Oct 16, 2019
commit c52943847fb3555c90bf09d8470123983e646151
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,81 @@
using BenchmarkDotNet.Attributes;
using MicroBenchmarks;

//#pragma warning disable CS1998 // async methods without awaits

namespace System.Threading.Tasks.Dataflow.Tests
{
public class UnboundedBufferBlockPerfTests : DefaultPropagatorPerfTests
{
public override IPropagatorBlock<int, int> CreateBlock() => new BufferBlock<int>();
}

public class BoundedBufferBlockPerfTests : DefaultBoundedPropagatorPerfTests
{
public override IPropagatorBlock<int, int> CreateBlock() => new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 100 });
}

public class ActionBlockPerfTests : DefaultTargetPerfTests
{
public override ITargetBlock<int> CreateBlock() => new ActionBlock<int>(i => { });
}

[BenchmarkCategory(Categories.CoreFX)]
public class Perf_Dataflow
public abstract class PerfTests<T> where T : IDataflowBlock
{
protected T block;

public abstract T CreateBlock();

[GlobalSetup]
public void BlockSetup()
{
block = CreateBlock();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this GlobalSetup still needed when we're calling BlockSetup on each benchmark invocation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only call BlockSetup from the benchmark code when we are forced to call Complete on the tested block to have a valid test case. This concerns only two benchmarks.


[Benchmark]
public async Task BufferBlock_Completion()
public async Task Completion()
{
var block = new BufferBlock<int>();
block.Complete();
await block.Completion;
manandre marked this conversation as resolved.
Show resolved Hide resolved
}
}

[BenchmarkCategory(Categories.CoreFX)]
public abstract class DefaultTargetPerfTests : PerfTests<ITargetBlock<int>> { }

[BenchmarkCategory(Categories.CoreFX)]
public abstract class TargetPerfTests<T> : PerfTests<T> where T : ITargetBlock<int>
{
[Benchmark(OperationsPerInvoke = 100_000)]
public void BufferBlock_Post()
public void Post()
{
var block = new BufferBlock<int>();
for (int i = 0; i < 100_000; i++)
{
block.Post(i);
}
}

[Benchmark(OperationsPerInvoke = 100_000)]
public async Task BufferBlock_SendAsync()
public async Task SendAsync()
{
var block = new BufferBlock<int>();
for (int i = 0; i < 100_000; i++)
{
await block.SendAsync(i);
}
}
}

[BenchmarkCategory(Categories.CoreFX)]
public abstract class DefaultBoundedPropagatorPerfTests : BoundedPropagatorPerfTests<IPropagatorBlock<int, int>> { }

[BenchmarkCategory(Categories.CoreFX)]
public abstract class DefaultPropagatorPerfTests : PropagatorPerfTests<IPropagatorBlock<int, int>> { }

[BenchmarkCategory(Categories.CoreFX)]
public abstract class PropagatorPerfTests<T> : BoundedPropagatorPerfTests<T> where T : IPropagatorBlock<int, int>
{
[Benchmark(OperationsPerInvoke = 100_000)]
public void BufferBlock_PostReceiveSequential()
public void PostReceiveSequential()
{
var block = new BufferBlock<int>();
for (int i = 0; i < 100_000; i++)
{
block.Post(i);
Expand All @@ -56,9 +92,8 @@ public void BufferBlock_PostReceiveSequential()
}

[Benchmark(OperationsPerInvoke = 100_000)]
public async Task BufferBlock_SendReceiveAsyncSequential()
public async Task SendReceiveAsyncSequential()
{
var block = new BufferBlock<int>();
for (int i = 0; i < 100_000; i++)
{
await block.SendAsync(i);
Expand All @@ -69,22 +104,25 @@ public async Task BufferBlock_SendReceiveAsyncSequential()
await block.ReceiveAsync();
}
}
}

[BenchmarkCategory(Categories.CoreFX)]
public abstract class BoundedPropagatorPerfTests<T> : PerfTests<T> where T : IPropagatorBlock<int, int>
{
[Benchmark(OperationsPerInvoke = 100_000)]
public async Task BufferBlock_PostReceiveParallel()
public async Task PostReceiveParallel()
{
var block = new BufferBlock<int>();
await Task.WhenAll(Post(), Receive());
Task Post() => Task.Run(()=>

Task Post() => Task.Run(() =>
{
for (int i = 0; i < 100_000; i++)
{
block.Post(i);
while (!block.Post(i));
}
});

Task Receive() => Task.Run(()=>
Task Receive() => Task.Run(() =>
{
for (int i = 0; i < 100_000; i++)
{
Expand All @@ -94,11 +132,10 @@ Task Receive() => Task.Run(()=>
}

[Benchmark(OperationsPerInvoke = 100_000)]
public async Task BufferBlock_SendReceiveAsyncParallel()
public async Task SendReceiveAsyncParallel()
{
var block = new BufferBlock<int>();
await Task.WhenAll(SendAsync(), ReceiveAsync());

async Task SendAsync()
{
for (int i = 0; i < 100_000; i++)
Expand Down