diff --git a/src/benchmarks/micro/MicroBenchmarks.csproj b/src/benchmarks/micro/MicroBenchmarks.csproj index 4c2ea392201..1608945fa6b 100644 --- a/src/benchmarks/micro/MicroBenchmarks.csproj +++ b/src/benchmarks/micro/MicroBenchmarks.csproj @@ -109,6 +109,10 @@ + + + + diff --git a/src/benchmarks/micro/libraries/System.Collections/PriorityQueue/Perf_PriorityQueue.cs b/src/benchmarks/micro/libraries/System.Collections/PriorityQueue/Perf_PriorityQueue.cs new file mode 100644 index 00000000000..0b371351409 --- /dev/null +++ b/src/benchmarks/micro/libraries/System.Collections/PriorityQueue/Perf_PriorityQueue.cs @@ -0,0 +1,110 @@ +// 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; +using System.Linq; +using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Extensions; +using MicroBenchmarks; + +namespace System.Collections.Tests +{ + [BenchmarkCategory(Categories.Libraries, Categories.Collections, Categories.GenericCollections)] + [GenericTypeArguments(typeof(int), typeof(int))] + [GenericTypeArguments(typeof(string), typeof(string))] + [GenericTypeArguments(typeof(Guid), typeof(Guid))] + public class Perf_PriorityQueue + { + [Params(10, 100, 1000)] + public int Size; + + private (TElement Element, TPriority Priority)[] _items; + private PriorityQueue _priorityQueue; + private PriorityQueue _prePopulatedPriorityQueue; + + [GlobalSetup] + public void Setup() + { + _items = ValuesGenerator.Array(Size).Zip(ValuesGenerator.Array(Size)).ToArray(); + _priorityQueue = new PriorityQueue(initialCapacity: Size); + _prePopulatedPriorityQueue = new PriorityQueue(_items); + } + + [Benchmark] + public void HeapSort() + { + var queue = _priorityQueue; + queue.EnqueueRange(_items); + + while (queue.Count > 0) + { + queue.Dequeue(); + } + } + + [Benchmark] + public void Enumerate() + { + foreach (var _ in _prePopulatedPriorityQueue.UnorderedItems) + { + + } + } + + [Benchmark] + public void Dequeue_And_Enqueue() + { + // benchmarks dequeue and enqueue operations + // for heaps of fixed size. + + var queue = _priorityQueue; + var items = _items; + + // populate the heap: incorporated in the + // benchmark to achieve determinism. + foreach ((TElement element, TPriority priority) in items) + { + queue.Enqueue(element, priority); + } + + foreach ((TElement element, TPriority priority) in items) + { + queue.Dequeue(); + queue.Enqueue(element, priority); + } + + // Drain the heap + while (queue.Count > 0) + { + queue.Dequeue(); + } + } + + [Benchmark] + public void K_Max_Elements() + { + const int k = 5; + var queue = _priorityQueue; + var items = _items; + + for (int i = 0; i < k; i++) + { + (TElement element, TPriority priority) = items[i]; + queue.Enqueue(element, priority); + } + + for (int i = k; i < Size; i++) + { + (TElement element, TPriority priority) = items[i]; + queue.EnqueueDequeue(element, priority); + } + + for (int i = 0; i < k; i++) + { + queue.Dequeue(); + } + } + } +} diff --git a/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs b/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs index 157aef81227..87bf6d82d8d 100644 --- a/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs +++ b/src/harness/BenchmarkDotNet.Extensions/ValuesGenerator.cs @@ -112,6 +112,8 @@ private static T GenerateValue(Random random) return (T)(object)(random.NextDouble() > 0.5); if (typeof(T) == typeof(string)) return (T)(object)GenerateRandomString(random, 1, 50); + if (typeof(T) == typeof(Guid)) + return (T)(object)GenerateRandomGuid(random); throw new NotImplementedException($"{typeof(T).Name} is not implemented"); } @@ -135,5 +137,12 @@ private static string GenerateRandomString(Random random, int minLength, int max return builder.ToString(); } + + private static Guid GenerateRandomGuid(Random random) + { + byte[] bytes = new byte[16]; + random.NextBytes(bytes); + return new Guid(bytes); + } } } \ No newline at end of file