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 | - | - | - | - |