From d2be77afef65a8a3025ef7b15929d2bfb73d4487 Mon Sep 17 00:00:00 2001 From: Reegeek Date: Tue, 30 Jun 2020 16:35:24 +0200 Subject: [PATCH] [Repeat] add Repeat generator. --- .../RangeWhereSelectSum.cs | 3 +- src/StructLinq.Benchmark/Repeat.cs | 54 +++++++++++++++++++ src/StructLinq.Tests/RepeatTests.cs | 26 +++++++++ src/StructLinq/Repeat/RepeatEnumerable.cs | 24 +++++++++ src/StructLinq/Repeat/RepeatEnumerator.cs | 31 +++++++++++ src/StructLinq/Repeat/StructEnumerable.cs | 15 ++++++ 6 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/StructLinq.Benchmark/Repeat.cs create mode 100644 src/StructLinq.Tests/RepeatTests.cs create mode 100644 src/StructLinq/Repeat/RepeatEnumerable.cs create mode 100644 src/StructLinq/Repeat/RepeatEnumerator.cs create mode 100644 src/StructLinq/Repeat/StructEnumerable.cs diff --git a/src/StructLinq.Benchmark/RangeWhereSelectSum.cs b/src/StructLinq.Benchmark/RangeWhereSelectSum.cs index 927cd9a2..0eb8793f 100644 --- a/src/StructLinq.Benchmark/RangeWhereSelectSum.cs +++ b/src/StructLinq.Benchmark/RangeWhereSelectSum.cs @@ -27,6 +27,7 @@ public class RangeWhereSelectSum public RangeWhereSelectSum() { } + [Benchmark(Baseline = true)] public int SysSum() { @@ -41,6 +42,7 @@ public int SysSum() } return sum; } + [Benchmark] public int SysRangeWhereSelectSum() => Enumerable.Range(0, Count) .Where(x=> (x & 1)==0) @@ -81,5 +83,4 @@ public readonly int Eval(int element) return element * 2; } } - } \ No newline at end of file diff --git a/src/StructLinq.Benchmark/Repeat.cs b/src/StructLinq.Benchmark/Repeat.cs new file mode 100644 index 00000000..26172053 --- /dev/null +++ b/src/StructLinq.Benchmark/Repeat.cs @@ -0,0 +1,54 @@ +using System.Linq; +using BenchmarkDotNet.Attributes; + +namespace StructLinq.Benchmark +{ + + //``` ini + + //BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 + //Intel Core i7-7700 CPU 3.60GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores + //.NET Core SDK=3.1.301 + //[Host] : .NET Core 3.1.5 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.27001), X64 RyuJIT + //DefaultJob : .NET Core 3.1.5 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.27001), X64 RyuJIT + + + //``` + //| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | + //|----------------------- |----------:|----------:|----------:|------:|------:|------:|------:|----------:| + //| EnumerableRepeat | 38.829 us | 0.3285 us | 0.2912 us | 1.00 | - | - | - | 32 B | + //| StructEnumerableRepeat | 2.883 us | 0.0074 us | 0.0066 us | 0.07 | - | - | - | - | + + [MemoryDiagnoser] + public class Repeat + { + private const int Count = 10000; + private const int value = 12; + + [Benchmark(Baseline = true)] + public int EnumerableRepeat() + { + int sum = 0; + foreach (var result in Enumerable.Repeat(value, Count)) + { + sum += result; + } + + return sum; + } + + [Benchmark] + public int StructEnumerableRepeat() + { + int sum = 0; + foreach (var result in StructEnumerable.Repeat(value, Count)) + { + sum += result; + } + + return sum; + } + + + } +} diff --git a/src/StructLinq.Tests/RepeatTests.cs b/src/StructLinq.Tests/RepeatTests.cs new file mode 100644 index 00000000..5c5c35b2 --- /dev/null +++ b/src/StructLinq.Tests/RepeatTests.cs @@ -0,0 +1,26 @@ +using System.Linq; +using FluentAssertions; +using StructLinq.Repeat; +using Xunit; + +namespace StructLinq.Tests +{ + public class RepeatTests : AbstractEnumerableTests, RepeatEnumerator> + { + protected override RepeatEnumerable Build(int size) + { + return StructEnumerable.Repeat(-1, (uint)size); + } + + [Theory] + [InlineData(0, 10)] + [InlineData(-10, 20)] + [InlineData(-20, 10)] + public void ShouldBeEqualToSystem(int element, int count) + { + var system = Enumerable.Repeat(element, count); + var structEnum = StructEnumerable.Repeat(element, (uint)count).ToEnumerable(); + structEnum.Should().Equal(system); + } + } +} diff --git a/src/StructLinq/Repeat/RepeatEnumerable.cs b/src/StructLinq/Repeat/RepeatEnumerable.cs new file mode 100644 index 00000000..c7a7c7d3 --- /dev/null +++ b/src/StructLinq/Repeat/RepeatEnumerable.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace StructLinq.Repeat +{ + public readonly struct RepeatEnumerable : IStructEnumerable> + { + private readonly T element; + private readonly uint count; + + public RepeatEnumerable(T element, uint count) + { + this.element = element; + this.count = count; + } + + public RepeatEnumerator GetEnumerator() + { + return new RepeatEnumerator(element, count); + } + } +} diff --git a/src/StructLinq/Repeat/RepeatEnumerator.cs b/src/StructLinq/Repeat/RepeatEnumerator.cs new file mode 100644 index 00000000..8aabb0a5 --- /dev/null +++ b/src/StructLinq/Repeat/RepeatEnumerator.cs @@ -0,0 +1,31 @@ +namespace StructLinq.Repeat +{ + public struct RepeatEnumerator : IStructEnumerator + { + private readonly T element; + private readonly uint count; + private uint index; + public RepeatEnumerator(T element, uint count) + { + this.element = element; + this.count = count; + index = 0; + } + + public void Dispose() + { + } + + public bool MoveNext() + { + return index++ < count; + } + + public void Reset() + { + index = 0; + } + + public T Current => element; + } +} diff --git a/src/StructLinq/Repeat/StructEnumerable.cs b/src/StructLinq/Repeat/StructEnumerable.cs new file mode 100644 index 00000000..281848a9 --- /dev/null +++ b/src/StructLinq/Repeat/StructEnumerable.cs @@ -0,0 +1,15 @@ +using System.Runtime.CompilerServices; +using StructLinq.Repeat; + +// ReSharper disable once CheckNamespace +namespace StructLinq +{ + public static partial class StructEnumerable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RepeatEnumerable Repeat(T element, uint count) + { + return new RepeatEnumerable(element, count); + } + } +}