From d7ba3edc1588079d0509065db0d0d0e344b59cd0 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 29 Jun 2018 20:16:02 +0200 Subject: [PATCH 1/4] copy --- .../System.Threading.Channels/Perf.Channel.cs | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs diff --git a/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs new file mode 100644 index 00000000000..c9c1a089a42 --- /dev/null +++ b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs @@ -0,0 +1,130 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.Xunit.Performance; +using System.Threading.Channels; + +namespace System.Threading.Channels.Tests +{ + public sealed class UnboundedChannelPerfTests : PerfTests + { + public override Channel CreateChannel() => Channel.CreateUnbounded(); + } + + public sealed class SpscUnboundedChannelPerfTests : PerfTests + { + public override Channel CreateChannel() => Channel.CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true }); + } + + public sealed class BoundedChannelPerfTests : PerfTests + { + public override Channel CreateChannel() => Channel.CreateBounded(10); + } + + public abstract class PerfTests + { + public abstract Channel CreateChannel(); + + [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + public void TryWriteThenTryRead() + { + Channel channel = CreateChannel(); + ChannelReader reader = channel.Reader; + ChannelWriter writer = channel.Writer; + + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + long iters = Benchmark.InnerIterationCount; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < iters; i++) + { + writer.TryWrite(i); + reader.TryRead(out _); + } + } + } + } + + [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + public async Task WriteAsyncThenReadAsync() + { + Channel channel = CreateChannel(); + ChannelReader reader = channel.Reader; + ChannelWriter writer = channel.Writer; + + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + long iters = Benchmark.InnerIterationCount; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < iters; i++) + { + await writer.WriteAsync(i); + await reader.ReadAsync(); + } + } + } + } + + [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + public async Task ReadAsyncThenWriteAsync() + { + Channel channel = CreateChannel(); + ChannelReader reader = channel.Reader; + ChannelWriter writer = channel.Writer; + + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + long iters = Benchmark.InnerIterationCount; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < iters; i++) + { + ValueTask r = reader.ReadAsync(); + await writer.WriteAsync(42); + await r; + } + } + } + } + + [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + public async Task PingPong() + { + Channel channel1 = CreateChannel(); + Channel channel2 = CreateChannel(); + + foreach (BenchmarkIteration iteration in Benchmark.Iterations) + { + long iters = Benchmark.InnerIterationCount; + using (iteration.StartMeasurement()) + { + await Task.WhenAll( + Task.Run(async () => + { + ChannelReader reader = channel1.Reader; + ChannelWriter writer = channel2.Writer; + for (int i = 0; i < iters; i++) + { + await writer.WriteAsync(i); + await reader.ReadAsync(); + } + }), + Task.Run(async () => + { + ChannelWriter writer = channel1.Writer; + ChannelReader reader = channel2.Reader; + for (int i = 0; i < iters; i++) + { + await reader.ReadAsync(); + await writer.WriteAsync(i); + } + })); + } + } + } + } +} From d380f0ae515f711a2e2694530a2e98179172533b Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 29 Jun 2018 20:17:39 +0200 Subject: [PATCH 2/4] port --- src/benchmarks/Benchmarks.csproj | 1 + .../System.Threading.Channels/Perf.Channel.cs | 151 ++++++++---------- 2 files changed, 70 insertions(+), 82 deletions(-) diff --git a/src/benchmarks/Benchmarks.csproj b/src/benchmarks/Benchmarks.csproj index 442ba6d2c35..22cfa92b543 100644 --- a/src/benchmarks/Benchmarks.csproj +++ b/src/benchmarks/Benchmarks.csproj @@ -26,6 +26,7 @@ + diff --git a/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs index c9c1a089a42..cbd22d4bba3 100644 --- a/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs +++ b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs @@ -3,128 +3,115 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; -using Microsoft.Xunit.Performance; -using System.Threading.Channels; +using BenchmarkDotNet.Attributes; namespace System.Threading.Channels.Tests { - public sealed class UnboundedChannelPerfTests : PerfTests + public class UnboundedChannelPerfTests : PerfTests { - public override Channel CreateChannel() => Channel.CreateUnbounded(); + public sealed override Channel CreateChannel() => Channel.CreateUnbounded(); } - public sealed class SpscUnboundedChannelPerfTests : PerfTests + public class SpscUnboundedChannelPerfTests : PerfTests { - public override Channel CreateChannel() => Channel.CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true }); + public sealed override Channel CreateChannel() => Channel.CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true }); } - public sealed class BoundedChannelPerfTests : PerfTests + public class BoundedChannelPerfTests : PerfTests { - public override Channel CreateChannel() => Channel.CreateBounded(10); + public sealed override Channel CreateChannel() => Channel.CreateBounded(10); } public abstract class PerfTests { + private Channel _channel, _channel1, _channel2; + private ChannelReader _reader; + private ChannelWriter _writer; + public abstract Channel CreateChannel(); - [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + [GlobalSetup(Target = nameof(TryWriteThenTryRead) + "," + nameof(WriteAsyncThenReadAsync) + "," + nameof(ReadAsyncThenWriteAsync))] + public void SingleChannelSetup() + { + _channel = CreateChannel(); + _reader = _channel.Reader; + _writer = _channel.Writer; + } + + [Benchmark] public void TryWriteThenTryRead() { - Channel channel = CreateChannel(); - ChannelReader reader = channel.Reader; - ChannelWriter writer = channel.Writer; + ChannelReader reader = _reader; + ChannelWriter writer = _writer; - foreach (BenchmarkIteration iteration in Benchmark.Iterations) + for (int i = 0; i < 1_000_000; i++) { - long iters = Benchmark.InnerIterationCount; - using (iteration.StartMeasurement()) - { - for (int i = 0; i < iters; i++) - { - writer.TryWrite(i); - reader.TryRead(out _); - } - } + writer.TryWrite(i); + reader.TryRead(out _); } } - [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + [Benchmark] public async Task WriteAsyncThenReadAsync() { - Channel channel = CreateChannel(); - ChannelReader reader = channel.Reader; - ChannelWriter writer = channel.Writer; + ChannelReader reader = _reader; + ChannelWriter writer = _writer; - foreach (BenchmarkIteration iteration in Benchmark.Iterations) + for (int i = 0; i < 1_000_000; i++) { - long iters = Benchmark.InnerIterationCount; - using (iteration.StartMeasurement()) - { - for (int i = 0; i < iters; i++) - { - await writer.WriteAsync(i); - await reader.ReadAsync(); - } - } + await writer.WriteAsync(i); + await reader.ReadAsync(); } } - [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + [Benchmark] public async Task ReadAsyncThenWriteAsync() { - Channel channel = CreateChannel(); - ChannelReader reader = channel.Reader; - ChannelWriter writer = channel.Writer; + ChannelReader reader = _reader; + ChannelWriter writer = _writer; - foreach (BenchmarkIteration iteration in Benchmark.Iterations) + for (int i = 0; i < 1_000_000; i++) { - long iters = Benchmark.InnerIterationCount; - using (iteration.StartMeasurement()) - { - for (int i = 0; i < iters; i++) - { - ValueTask r = reader.ReadAsync(); - await writer.WriteAsync(42); - await r; - } - } + ValueTask r = reader.ReadAsync(); + await writer.WriteAsync(42); + await r; } } - [Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations] + [GlobalSetup(Target = nameof(PingPong))] + public void SetupTwoChannels() + { + _channel1 = CreateChannel(); + _channel2 = CreateChannel(); + } + + [Benchmark] public async Task PingPong() { - Channel channel1 = CreateChannel(); - Channel channel2 = CreateChannel(); + Channel channel1 = _channel1; + Channel channel2 = _channel2; - foreach (BenchmarkIteration iteration in Benchmark.Iterations) - { - long iters = Benchmark.InnerIterationCount; - using (iteration.StartMeasurement()) + await Task.WhenAll( + Task.Run(async () => { - await Task.WhenAll( - Task.Run(async () => - { - ChannelReader reader = channel1.Reader; - ChannelWriter writer = channel2.Writer; - for (int i = 0; i < iters; i++) - { - await writer.WriteAsync(i); - await reader.ReadAsync(); - } - }), - Task.Run(async () => - { - ChannelWriter writer = channel1.Writer; - ChannelReader reader = channel2.Reader; - for (int i = 0; i < iters; i++) - { - await reader.ReadAsync(); - await writer.WriteAsync(i); - } - })); - } - } + ChannelReader reader = channel1.Reader; + ChannelWriter writer = channel2.Writer; + for (int i = 0; i < 1_000_000; i++) + { + await writer.WriteAsync(i); + await reader.ReadAsync(); + } + }), + Task.Run(async () => + { + ChannelWriter writer = channel1.Writer; + ChannelReader reader = channel2.Reader; + for (int i = 0; i < 1_000_000; i++) + { + await reader.ReadAsync(); + await writer.WriteAsync(i); + } + })); } } -} +} \ No newline at end of file From 6b5dfb04d53b87341e2aadeb44b9972d1d12a5b0 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 29 Jun 2018 21:11:28 +0200 Subject: [PATCH 3/4] add the category --- src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs index cbd22d4bba3..4efc9ab07cf 100644 --- a/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs +++ b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; +using Benchmarks; namespace System.Threading.Channels.Tests { @@ -22,6 +23,7 @@ public class BoundedChannelPerfTests : PerfTests public sealed override Channel CreateChannel() => Channel.CreateBounded(10); } + [BenchmarkCategory(Categories.CoreFX)] public abstract class PerfTests { private Channel _channel, _channel1, _channel2; From cf122c655385d0c31deca2746647748061f5a375 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Tue, 3 Jul 2018 14:44:14 +0200 Subject: [PATCH 4/4] move magic number to a const --- .../corefx/System.Threading.Channels/Perf.Channel.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs index 4efc9ab07cf..8c2b32f071c 100644 --- a/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs +++ b/src/benchmarks/corefx/System.Threading.Channels/Perf.Channel.cs @@ -26,6 +26,8 @@ public class BoundedChannelPerfTests : PerfTests [BenchmarkCategory(Categories.CoreFX)] public abstract class PerfTests { + private const int InnerIterationCount = 1_000_000; + private Channel _channel, _channel1, _channel2; private ChannelReader _reader; private ChannelWriter _writer; @@ -46,7 +48,7 @@ public void TryWriteThenTryRead() ChannelReader reader = _reader; ChannelWriter writer = _writer; - for (int i = 0; i < 1_000_000; i++) + for (int i = 0; i < InnerIterationCount; i++) { writer.TryWrite(i); reader.TryRead(out _); @@ -59,7 +61,7 @@ public async Task WriteAsyncThenReadAsync() ChannelReader reader = _reader; ChannelWriter writer = _writer; - for (int i = 0; i < 1_000_000; i++) + for (int i = 0; i < InnerIterationCount; i++) { await writer.WriteAsync(i); await reader.ReadAsync(); @@ -72,7 +74,7 @@ public async Task ReadAsyncThenWriteAsync() ChannelReader reader = _reader; ChannelWriter writer = _writer; - for (int i = 0; i < 1_000_000; i++) + for (int i = 0; i < InnerIterationCount; i++) { ValueTask r = reader.ReadAsync(); await writer.WriteAsync(42); @@ -98,7 +100,7 @@ await Task.WhenAll( { ChannelReader reader = channel1.Reader; ChannelWriter writer = channel2.Writer; - for (int i = 0; i < 1_000_000; i++) + for (int i = 0; i < InnerIterationCount; i++) { await writer.WriteAsync(i); await reader.ReadAsync(); @@ -108,7 +110,7 @@ await Task.WhenAll( { ChannelWriter writer = channel1.Writer; ChannelReader reader = channel2.Reader; - for (int i = 0; i < 1_000_000; i++) + for (int i = 0; i < InnerIterationCount; i++) { await reader.ReadAsync(); await writer.WriteAsync(i);