From de983a9248eee040a4d4213da0011f9f16b3ba5c Mon Sep 17 00:00:00 2001 From: Dennis Corvers Date: Wed, 3 Feb 2021 17:29:41 +0100 Subject: [PATCH] Added Benchmark and bumped version --- Benchmark/Benchmark.csproj | 16 +++++ Benchmark/Program.cs | 104 +++++++++++++++++++++++++++ Lockless-Queue.sln | 8 ++- Lockless-Queue/Lockless-Queue.csproj | 2 + README.md | 14 ++++ 5 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 Benchmark/Benchmark.csproj create mode 100644 Benchmark/Program.cs diff --git a/Benchmark/Benchmark.csproj b/Benchmark/Benchmark.csproj new file mode 100644 index 0000000..96e8e94 --- /dev/null +++ b/Benchmark/Benchmark.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp2.1 + + + + + + + + + + + diff --git a/Benchmark/Program.cs b/Benchmark/Program.cs new file mode 100644 index 0000000..082f747 --- /dev/null +++ b/Benchmark/Program.cs @@ -0,0 +1,104 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; +using LocklessQueues; +using System; +using System.Collections.Generic; +using SysConcurrentQueue = System.Collections.Concurrent.ConcurrentQueue; + +namespace Benchmark +{ + class Program + { + static void Main(string[] args) + { + BenchmarkRunner.Run(); + Console.ReadLine(); + } + } + + [MemoryDiagnoser] + public class Benchmarks + { + const int COUNT = 128; + + readonly ConcurrentQueue _concurrentQueue; + readonly SysConcurrentQueue _systemConcurrentQueue; + readonly MPSCQueue _mpscQueue; + readonly SPSCQueue _spscQueue; + readonly Queue _queue; + + public Benchmarks() + { + _concurrentQueue = new ConcurrentQueue(COUNT, true); + _systemConcurrentQueue = new SysConcurrentQueue(); + _mpscQueue = new MPSCQueue(COUNT); + _spscQueue = new SPSCQueue(COUNT); + _queue = new Queue(COUNT); + } + + [Benchmark] + public void ConcurrentQueue() + { + // ADD values + for (int i = 0; i < COUNT; i++) + _concurrentQueue.TryEnqueue(i); + + for (int i = 0; i < COUNT; i++) + _concurrentQueue.TryDequeue(out long result); + + _concurrentQueue.Clear(); + } + + [Benchmark] + public void SysConcurrentQueue() + { + // ADD values + for (int i = 0; i < COUNT; i++) + _systemConcurrentQueue.Enqueue(i); + + for (int i = 0; i < COUNT; i++) + _systemConcurrentQueue.TryDequeue(out long result); + + _systemConcurrentQueue.Clear(); + } + + [Benchmark] + public void MPSCQueue() + { + // ADD values + for (int i = 0; i < COUNT; i++) + _mpscQueue.TryEnqueue(i); + + for (int i = 0; i < COUNT; i++) + _mpscQueue.TryDequeue(out long result); + + _mpscQueue.Clear(); + } + + [Benchmark] + public void SPSCQueue() + { + // ADD values + for (int i = 0; i < COUNT; i++) + _spscQueue.TryEnqueue(i); + + for (int i = 0; i < COUNT; i++) + _spscQueue.TryDequeue(out long result); + + _spscQueue.Clear(); + } + + [Benchmark] + public void Queue() + { + // ADD values + for (int i = 0; i < COUNT; i++) + _queue.Enqueue(i); + + for (int i = 0; i < COUNT; i++) + _queue.TryDequeue(out long result); + + _queue.Clear(); + } + } +} diff --git a/Lockless-Queue.sln b/Lockless-Queue.sln index 414ffd5..d6fc7ae 100644 --- a/Lockless-Queue.sln +++ b/Lockless-Queue.sln @@ -5,7 +5,9 @@ VisualStudioVersion = 15.0.28307.1300 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lockless-Queue", "Lockless-Queue\Lockless-Queue.csproj", "{E40F468B-84F2-4D29-8F8F-425EA84D44FA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocklessQueuesTests", "LocklessQueuesTests\LocklessQueuesTests.csproj", "{051B182C-7FC4-4F19-96AE-17C706002836}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LocklessQueuesTests", "LocklessQueuesTests\LocklessQueuesTests.csproj", "{051B182C-7FC4-4F19-96AE-17C706002836}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmark", "Benchmark\Benchmark.csproj", "{749C39AD-73C0-43F3-AF8F-D39348A552D0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {051B182C-7FC4-4F19-96AE-17C706002836}.Debug|Any CPU.Build.0 = Debug|Any CPU {051B182C-7FC4-4F19-96AE-17C706002836}.Release|Any CPU.ActiveCfg = Release|Any CPU {051B182C-7FC4-4F19-96AE-17C706002836}.Release|Any CPU.Build.0 = Release|Any CPU + {749C39AD-73C0-43F3-AF8F-D39348A552D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {749C39AD-73C0-43F3-AF8F-D39348A552D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {749C39AD-73C0-43F3-AF8F-D39348A552D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {749C39AD-73C0-43F3-AF8F-D39348A552D0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Lockless-Queue/Lockless-Queue.csproj b/Lockless-Queue/Lockless-Queue.csproj index e03b9ca..c9b7229 100644 --- a/Lockless-Queue/Lockless-Queue.csproj +++ b/Lockless-Queue/Lockless-Queue.csproj @@ -18,6 +18,8 @@ The Concurrent Queue implementation is a copy of the .Net 5.0 implementation wit Copyright (c) 2021 Dennis Corvers true https://github.com/DennisCorvers/Lockless-Queue/blob/master/LICENSE + 1.0.1 + lockless lockfree concurrent queue CAS diff --git a/README.md b/README.md index 5dfe5ae..52b472a 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,17 @@ The following queue implementations are present: - Concurrent Queue (Multi Producer, Multi Consumer). The Concurrent Queue implementation is a **copy** of the .Net 5.0 implementation with the added option for a fixed-size queue. This queue is lockless if/when it is instantiated as a fixed-size queue. + +## Benchmarks + +SysConcurrentQueue and Queue are the built-in .Net types. Where possible, a fixed-size queue has been used. + +The following Benchmarks execute Enqueueing 128 items, Dequeueing 128 items and finally clearing the Queue. The same methods are used for each queue where available. All Queue benchmarks are run in a single-threaded environment to demonstrate the "raw" throughput of each queue. + +| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | +|------------------- |-----------:|---------:|---------:|-------:|-------:|------:|----------:| +| ConcurrentQueue | 2,507.0 ns | 6.52 ns | 6.10 ns | - | - | - | - | +| SysConcurrentQueue | 2,943.2 ns | 23.93 ns | 21.21 ns | 0.7782 | 0.0153 | - | 4928 B | +| MPSCQueue | 1,655.7 ns | 1.30 ns | 1.22 ns | - | - | - | - | +| SPSCQueue | 512.7 ns | 3.13 ns | 2.93 ns | - | - | - | - | +| Queue | 588.7 ns | 1.75 ns | 1.63 ns | - | - | - | - |