diff --git a/Benchmarks/App.config b/Benchmarks/App.config index 3388e30..b801039 100644 --- a/Benchmarks/App.config +++ b/Benchmarks/App.config @@ -1,90 +1,30 @@  - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Benchmarks/BenchmarkAggregate.cs b/Benchmarks/BenchmarkAggregate.cs new file mode 100644 index 0000000..d302e62 --- /dev/null +++ b/Benchmarks/BenchmarkAggregate.cs @@ -0,0 +1,95 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFasterSpan; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksAggregate + { + private static readonly Func mulXInts = (acc, x) => acc += x * x; + + [BenchmarkCategory("BAg_IntArrayAggregate"), Benchmark(Baseline = true)] + public double IntArrayAggregateLinq() + { + return Benchmarks.intArray.Aggregate(0.0D, mulXInts); + } + + [BenchmarkCategory("BAg_IntArrayAggregate"), Benchmark] + public double IntArrayAggregateFast() + { + return Benchmarks.intArray.AggregateF(0.0D, mulXInts); + } + + [BenchmarkCategory("BAg_IntReadOnlyArrayAggregate"), Benchmark(Baseline = true)] + public double IntReadOnlyArrayAggregateLinq() + { + return Array.AsReadOnly(Benchmarks.intArray).Aggregate(0.0D, mulXInts); + } + + [BenchmarkCategory("BAg_IntReadOnlyArrayAggregate"), Benchmark] + public double IntReadOnlyArrayAggregateFast() + { + return Array.AsReadOnly(Benchmarks.intArray).AggregateF(0.0D, mulXInts); + } + + [BenchmarkCategory("BAg_IntSpanAggregate"), Benchmark(Baseline = true)] + public double IntSpanAggregateForEach() + { + //return intArray.AsSpan().Aggregate(0.0, mulXInts); + double result = 0.0D; + foreach (var v in Benchmarks.intArray.AsSpan()) + { + result = mulXInts(result, v); + } + return result; + } + + [BenchmarkCategory("BAg_IntSpanAggregate"), Benchmark] + public double IntSpanAggregateFast() + { + return Benchmarks.intArray.AsSpan().AggregateF(0.0, mulXInts); + } + + [BenchmarkCategory("BAg_intList.Aggregate.Select"), Benchmark(Baseline = true)] + public double IntArrayAggregateLinqSelector() + { + return Benchmarks.intArray.Aggregate(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); + } + + [BenchmarkCategory("BAg_intList.Aggregate.Select"), Benchmark] + public double IntArrayAggregateFastSelector() + { + return Benchmarks.intArray.AggregateF(0.0, mulXInts, acc => acc / Benchmarks.intArray.Length); + } + + [BenchmarkCategory("BAg_intList.Aggregate"), Benchmark(Baseline = true)] + public double IntListAggregateLinq() + { + return Benchmarks.intList.Aggregate(0.0, mulXInts); + } + + [BenchmarkCategory("BAg_intList.Aggregate"), Benchmark] + public double IntListAggregateFast() + { + return Benchmarks.intList.AggregateF(0.0, mulXInts); + } + + [BenchmarkCategory("BAg_intList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntReadOnlyListAggregateLinq() + { + return Benchmarks.intList.AsReadOnly().Aggregate(0.0, mulXInts); + } + + [BenchmarkCategory("BAg_intList.AsReadOnly"), Benchmark] + public double IntReadOnlyListAggregateFast() + { + return Benchmarks.intList.AsReadOnly().AggregateF(0.0, mulXInts); + } + } +} diff --git a/Benchmarks/BenchmarkAverage.cs b/Benchmarks/BenchmarkAverage.cs new file mode 100644 index 0000000..b089008 --- /dev/null +++ b/Benchmarks/BenchmarkAverage.cs @@ -0,0 +1,53 @@ +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFaster.SIMD; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksAverage + { + + [BenchmarkCategory("BAvintArray"), Benchmark(Baseline = true)] + public double IntArrayAverageLinq() + { + return Benchmarks.intArray.Average(); + } + + [BenchmarkCategory("BAvintArray"), Benchmark] + public double IntArrayAverageFast() + { + return Benchmarks.intArray.AverageF(); + } + + [BenchmarkCategory("BAvintArray"), Benchmark] + public double IntArrayAverageFastSIMD() + { + return Benchmarks.intArray.AverageS(); + } + + + [BenchmarkCategory("BAvintList"), Benchmark(Baseline = true)] + public double IntListAverageLinq() + { + return Benchmarks.intList.Average(); + } + + [BenchmarkCategory("BAvintList"), Benchmark] + public double IntListAverageFast() + { + return Benchmarks.intList.AverageF(); + } + + //[BenchmarkCategory("BAvintList"), Benchmark] + //public double IntListAverageFastSIMD() + //{ + // return Benchmarks.intList.AverageS(); + //} + + } +} diff --git a/Benchmarks/BenchmarkFirst.cs b/Benchmarks/BenchmarkFirst.cs new file mode 100644 index 0000000..591e6ed --- /dev/null +++ b/Benchmarks/BenchmarkFirst.cs @@ -0,0 +1,98 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFasterSpan; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksFirst + { + private static readonly Func firstInts = (x) => x > 0; + + [BenchmarkCategory("BFintArray"), Benchmark(Baseline = true)] + public double IntArrayFirstLinqSelector() + { + return Benchmarks.intArray.First(firstInts); + } + + [BenchmarkCategory("BFintArray"), Benchmark] + public double IntArrayFirstArrayFindSelector() + { + Predicate predicate = new Predicate(firstInts); + return Array.Find(Benchmarks.intArray, predicate); + } + + [BenchmarkCategory("BFintArray"), Benchmark] + public double IntArrayFirstFastSelector() + { + return Benchmarks.intArray.FirstF(firstInts); + } + + + [BenchmarkCategory("BFlocalArray.AsSpan"), Benchmark(Baseline = true)] + public double IntSpanFirstForEachSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + foreach (int i in asSpan) + { + if (firstInts(i)) + { + return i; + } + } + + return 0; + } + + [BenchmarkCategory("BFlocalArray.AsSpan"), Benchmark] + public double IntSpanFirstFastSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.FirstF(firstInts); + } + + [BenchmarkCategory("BFintList"), Benchmark(Baseline = true)] + public double IntListFirstLinqSelector() + { + return Benchmarks.intList.First(firstInts); + } + + [BenchmarkCategory("BFintList"), Benchmark] + public double IntListFirstFastSelector() + { + return Benchmarks.intList.FirstF(firstInts); + } + + [BenchmarkCategory("BFintList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyFirstLinqSelector() + { + return Benchmarks.intList.AsReadOnly().First(firstInts); + } + + [BenchmarkCategory("BFintList.AsReadOnly"), Benchmark] + public double IntAsListReadOnlyFirstFastSelector() + { + return Benchmarks.intList.AsReadOnly().FirstF(firstInts); + } + + [BenchmarkCategory("BFArray.AsReadOnly"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyFirstLinqSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).First(firstInts); + } + + [BenchmarkCategory("BFArray.AsReadOnly"), Benchmark] + public double IntArrayAsReadOnlyFirstFastSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).FirstF(firstInts); + } + + } +} diff --git a/Benchmarks/BenchmarkLast.cs b/Benchmarks/BenchmarkLast.cs new file mode 100644 index 0000000..0dba2fb --- /dev/null +++ b/Benchmarks/BenchmarkLast.cs @@ -0,0 +1,99 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFasterSpan; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarksLast + { + private static readonly Func LastInts = (x) => x > 0; + + + [BenchmarkCategory("BLintArray"), Benchmark(Baseline = true)] + public double IntArrayLastLinqSelector() + { + return Benchmarks.intArray.Last(LastInts); + } + + [BenchmarkCategory("BLintArray"), Benchmark] + public double IntArrayLastArrayFindSelector() + { + Predicate predicate = new Predicate(LastInts); + return Array.FindLast(Benchmarks.intArray, predicate); + } + + [BenchmarkCategory("BLintArray"), Benchmark] + public double IntArrayLastFastSelector() + { + return Benchmarks.intArray.LastF(LastInts); + } + + + + [BenchmarkCategory("BLlocalArray.AsSpan"), Benchmark(Baseline = true)] + public double IntSpanLastForEachSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + foreach (int i in asSpan) + { + if (LastInts(i)) + { + return i; + } + } + + return 0; + } + + [BenchmarkCategory("BLlocalArray.AsSpan"), Benchmark] + public double IntSpanLastFastSelector() + { + int[] localArray = Benchmarks.intArray; + Span asSpan = localArray.AsSpan(); + return asSpan.LastF(LastInts); + } + + [BenchmarkCategory("BLintList"), Benchmark(Baseline = true)] + public double IntListLastLinqSelector() + { + return Benchmarks.intList.Last(LastInts); + } + + [BenchmarkCategory("BLintList"), Benchmark] + public double IntListLastFastSelector() + { + return Benchmarks.intList.LastF(LastInts); + } + + [BenchmarkCategory("BLintList.AsReadOnly"), Benchmark(Baseline = true)] + public double IntAsListReadOnlyLastLinqSelector() + { + return Benchmarks.intList.AsReadOnly().Last(LastInts); + } + + [BenchmarkCategory("BLintList.AsReadOnly"), Benchmark] + public double IntAsListReadOnlyLastFastSelector() + { + return Benchmarks.intList.AsReadOnly().LastF(LastInts); + } + + [BenchmarkCategory("BLArray.AsReadOnly"), Benchmark(Baseline = true)] + public double IntArrayAsReadOnlyLastLinqSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).Last(LastInts); + } + + [BenchmarkCategory("BLArray.AsReadOnly"), Benchmark] + public double IntArrayAsReadOnlyLastFastSelector() + { + return Array.AsReadOnly(Benchmarks.intArray).LastF(LastInts); + } + } +} diff --git a/Benchmarks/BenchmarkOrderBy.cs b/Benchmarks/BenchmarkOrderBy.cs new file mode 100644 index 0000000..7b44846 --- /dev/null +++ b/Benchmarks/BenchmarkOrderBy.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkOrderBy + { + private static readonly Func orderBy = (x) => x - 1; + + [BenchmarkCategory("BOBintArray"), Benchmark(Baseline = true)] + public int IntArrayOrderByLinq() + { + return Benchmarks.intArray.OrderBy(orderBy).Sum(); + } + + [BenchmarkCategory("BOBintArray"), Benchmark] + public int IntArrayOrderByFast() + { + return Benchmarks.intArray.OrderByF(orderBy).Sum(); + } + } +} diff --git a/Benchmarks/BenchmarkSelect.cs b/Benchmarks/BenchmarkSelect.cs new file mode 100644 index 0000000..b175aa6 --- /dev/null +++ b/Benchmarks/BenchmarkSelect.cs @@ -0,0 +1,34 @@ +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFaster.SIMD; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkSelect + { + [BenchmarkCategory("BSintArray.Select"), Benchmark(Baseline = true)] + public int[] IntArraySelectLinq() + { + return Benchmarks.intArray.Select(x => x * x).ToArray(); + } + + [BenchmarkCategory("BSintArray.Select"), Benchmark] + public int[] IntArraySelectFast() + { + return Benchmarks.intArray.SelectF(x => x * x); + } + + [BenchmarkCategory("BSintArray.Select"), Benchmark] + public int[] IntArraySelectFastSIMD() + { + return Benchmarks.intArray.SelectS(x => x * x, x => x * x); + } + + + } +} diff --git a/Benchmarks/BenchmarkSequenceEqual.cs b/Benchmarks/BenchmarkSequenceEqual.cs new file mode 100644 index 0000000..63e509e --- /dev/null +++ b/Benchmarks/BenchmarkSequenceEqual.cs @@ -0,0 +1,49 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFaster.Parallel; +using JM.LinqFaster.SIMD; +using JM.LinqFaster.SIMD.Parallel; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkSequenceEqual + { + [BenchmarkCategory("BSEintArray"), Benchmark(Baseline = true)] + public bool IntArraySequenceEqual() + { + return Benchmarks.intArray.SequenceEqual(Benchmarks.array2); + } + + [BenchmarkCategory("BSEintArray"), Benchmark] + public bool IntArraySequenceEqualF() + { + return Benchmarks.intArray.SequenceEqualF(Benchmarks.array2); + } + + + [BenchmarkCategory("BSEintArray"), Benchmark] + public bool IntArraySequenceEqualP() + { + return Benchmarks.intArray.SequenceEqualP(Benchmarks.array2); + } + + [BenchmarkCategory("BSEintArray"), Benchmark] + public bool IntArraySequenceEqualS() + { + return Benchmarks.intArray.SequenceEqualS(Benchmarks.array2); + } + + [BenchmarkCategory("BSEintArray"), Benchmark] + public bool IntArraySequenceEqualSP() + { + return Benchmarks.intArray.SequenceEqualSP(Benchmarks.array2); + } + + } +} diff --git a/Benchmarks/BenchmarkSum.cs b/Benchmarks/BenchmarkSum.cs new file mode 100644 index 0000000..c7d7cc0 --- /dev/null +++ b/Benchmarks/BenchmarkSum.cs @@ -0,0 +1,263 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFasterSpan; +using JM.LinqFaster.SIMD; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkSum + { + private static readonly Func sumDivide = (x) => x / 2; + + [BenchmarkCategory("BSumbyteArray"), Benchmark(Baseline = true)] + public int ByteArraySumLinq() + { + return Benchmarks.byteArray.Aggregate(0, (current, b1) => current + b1); + } + + [BenchmarkCategory("BSumbyteArray"), Benchmark] + public uint ByteArraySumFast() + { + return Benchmarks.byteArray.SumF(); + } + + + [BenchmarkCategory("BSumshortArray"), Benchmark(Baseline = true)] + public int ShortArraySumLinq() + { + return Benchmarks.shortArray.Aggregate(0, (current, s1) => current + s1); + } + + [BenchmarkCategory("BSumshortArray"), Benchmark] + public int ShortArraySumFast() + { + return Benchmarks.shortArray.SumF(); + } + + + [BenchmarkCategory("BSumintArray"), Benchmark(Baseline = true)] + public int IntArraySumLinq() + { + return Benchmarks.intArray.Sum(); + } + + [BenchmarkCategory("BSumintArray"), Benchmark] + public int IntArraySumFast() + { + return Benchmarks.intArray.SumF(); + } + + [BenchmarkCategory("BSumintArray"), Benchmark] + public int IntArraySumFastSIMD() + { + return Benchmarks.intArray.SumS(); + } + + [BenchmarkCategory("BSumintArraySpan"), Benchmark(Baseline = true)] + public int IntSpanSumFor() + { + int val = 0; + Span span = Benchmarks.intArray.AsSpan(); + for (int index = 0; index < span.Length; index++) + { + val += span[index]; + } + + return val; + } + + [BenchmarkCategory("BSumintArraySpan"), Benchmark] + public int IntSpanSumFast() + { + return Benchmarks.intArray.AsSpan().SumF(); + } + + [BenchmarkCategory("BSumintList"), Benchmark(Baseline = true)] + public int IntListSumLinq() + { + return Benchmarks.intList.Sum(); + } + + [BenchmarkCategory("BSumintList"), Benchmark] + public int IntListSumFast() + { + return Benchmarks.intList.SumF(); + } + + + [BenchmarkCategory("BSumIntArrayAggregate"), Benchmark(Baseline = true)] + public int IntArraySumLinqSelect() + { + return Benchmarks.intArray.Sum(sumDivide); + } + + [BenchmarkCategory("BSumIntArrayAggregate"), Benchmark] + public int IntArraySumFastSelect() + { + return Benchmarks.intArray.SumF(sumDivide); + } + + [BenchmarkCategory("BSumintArrayAsReadOnly"), Benchmark(Baseline = true)] + public double IntReadOnlyArraySumWithSelectLinq() + { + return Array.AsReadOnly(Benchmarks.intArray).Sum(sumDivide); + } + + [BenchmarkCategory("BSumintArrayAsReadOnly"), Benchmark] + public double IntReadOnlyArraySumWithSelectFast() + { + return Array.AsReadOnly(Benchmarks.intArray).SumF(sumDivide); + } + + [BenchmarkCategory("BSumintNullArray"), Benchmark(Baseline = true)] + public int? IntNullArraySumLinq() + { + return Benchmarks.intNullArray.Sum(); + } + + [BenchmarkCategory("BSumintNullArray"), Benchmark] + public int? IntNullArraySumFast() + { + return Benchmarks.intNullArray.SumF(); + } + + [BenchmarkCategory("BSumintNullArraySelect"), Benchmark(Baseline = true)] + public int IntNullArraySumLinqSelect() + { + return Benchmarks.intNullArray.Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("BSumintNullArraySelect"), Benchmark] + public int IntNullArraySumFastSelect() + { + return Benchmarks.intNullArray.SumF(x => x / 2 ?? 0); + } + + [BenchmarkCategory("BSumfloatArray"), Benchmark(Baseline = true)] + public float FloatArraySumLinq() + { + return Benchmarks.floatArray.Sum(); + } + + [BenchmarkCategory("BSumfloatArray"), Benchmark] + public float FloatArraySumFast() + { + return Benchmarks.floatArray.SumF(); + } + + [BenchmarkCategory("BSumfloatList"), Benchmark(Baseline = true)] + public float FloatListSumLinq() + { + return Benchmarks.floatList.Sum(); + } + + [BenchmarkCategory("BSumfloatList"), Benchmark] + public float FloatListSumFast() + { + return Benchmarks.floatList.SumF(); + } + + [BenchmarkCategory("BSumfloatArraySelect"), Benchmark(Baseline = true)] + public float FloatArraySumLinqSelect() + { + return Benchmarks.floatArray.Sum(x => x / 2); + } + + [BenchmarkCategory("BSumfloatArraySelect"), Benchmark] + public float FloatArraySumFastSelect() + { + return Benchmarks.floatArray.SumF(x => x / 2); + } + + [BenchmarkCategory("BSumfloatNullArray"), Benchmark(Baseline = true)] + public float? FloatNullArraySumLinq() + { + return Benchmarks.floatNullArray.Sum(); + } + + [BenchmarkCategory("BSumfloatNullArray"), Benchmark] + public float? FloatNullArraySumFast() + { + return Benchmarks.floatNullArray.SumF(); + } + + [BenchmarkCategory("BSumfloatNullArraySelect"), Benchmark(Baseline = true)] + public float FloatNullArraySumLinqSelect() + { + return Benchmarks.floatNullArray.Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("BSumfloatNullArraySelect"), Benchmark] + public float FloatNullArraySumFastSelect() + { + return Benchmarks.floatNullArray.SumF(x => x / 2 ?? 0); + } + + + [BenchmarkCategory("BSumdoubleArray"), Benchmark(Baseline = true)] + public double DoubleArraySumLinq() + { + return Benchmarks.doubleArray.Sum(); + } + + [BenchmarkCategory("BSumdoubleArray"), Benchmark] + public double DoubleArraySumFast() + { + return Benchmarks.doubleArray.SumF(); + } + + [BenchmarkCategory("BSumdoubleList"), Benchmark(Baseline = true)] + public double DoubleListSumLinq() + { + return Benchmarks.doubleList.Sum(); + } + + [BenchmarkCategory("BSumdoubleList"), Benchmark] + public double DoubleListSumFast() + { + return Benchmarks.doubleList.SumF(); + } + + [BenchmarkCategory("BSumdoubleArraySelect"), Benchmark(Baseline = true)] + public double DoubleArraySumLinqSelect() + { + return Benchmarks.doubleArray.Sum(x => x / 2); + } + + [BenchmarkCategory("BSumdoubleArraySelect"), Benchmark] + public double DoubleArraySumFastSelect() + { + return Benchmarks.doubleArray.SumF(x => x / 2); + } + + [BenchmarkCategory("BSumdoubleNullArray"), Benchmark(Baseline = true)] + public double? DoubleNullArraySumLinq() + { + return Benchmarks.doubleNullArray.Sum(); + } + + [BenchmarkCategory("BSumdoubleNullArray"), Benchmark] + public double? DoubleNullArraySumFast() + { + return Benchmarks.doubleNullArray.SumF(); + } + + [BenchmarkCategory("BSumdoubleNullArraySelect"), Benchmark(Baseline = true)] + public double? DoubleNullArraySumLinqSelect() + { + return Benchmarks.doubleNullArray.Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("BSumdoubleNullArraySelect"), Benchmark] + public double? DoubleNullArraySumFastSelect() + { + return Benchmarks.doubleNullArray.SumF(x => x / 2 ?? 0); + } + } +} diff --git a/Benchmarks/BenchmarkWhereSum.cs b/Benchmarks/BenchmarkWhereSum.cs new file mode 100644 index 0000000..5efe4ed --- /dev/null +++ b/Benchmarks/BenchmarkWhereSum.cs @@ -0,0 +1,293 @@ +using System; +using System.Linq; + +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +using JM.LinqFaster; +using JM.LinqFasterSpan; + +namespace Tests +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class BenchmarkWhereSum + { + + [BenchmarkCategory("BWSbyteArray"), Benchmark(Baseline = true)] + public int ByteArrayWhereSumLinq() + { + return Benchmarks.byteArray.Where(x => x > 0).Aggregate(0, (current, b1) => current + b1); + } + + [BenchmarkCategory("BWSbyteArray"), Benchmark] + public uint ByteArrayWhereSumFast() + { + return Benchmarks.byteArray.WhereSumF(x => x > 0); + } + + + [BenchmarkCategory("BWSshortArray"), Benchmark(Baseline = true)] + public int ShortArrayWhereSumLinq() + { + return Benchmarks.shortArray.Where(x => x > 0).Aggregate(0, (current, s1) => current + s1); + } + + [BenchmarkCategory("BWSshortArray"), Benchmark] + public int ShortArrayWhereSumFast() + { + return Benchmarks.shortArray.WhereSumF(x => x > 0); + } + + + [BenchmarkCategory("BWSintArray"), Benchmark(Baseline = true)] + public int IntArrayWhereSumLinq() + { + return Benchmarks.intArray.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSintArray"), Benchmark] + public int IntArrayWhereSumFast() + { + return Benchmarks.intArray.WhereSumF(x => x > 0); + } + + /* + [BenchmarkCategory("BWSintArray"), Benchmark] + public int IntArrayWhereSumFastSIMD() + { + return intArray.WhereSumS(x => x > 0); + } + */ + + + [BenchmarkCategory("BWSintArray.AsSpan"), Benchmark(Baseline = true)] + public int IntSpanWhereSumFor() + { + int val = 0; + Span span = Benchmarks.intArray.AsSpan(); + for (int index = 0; index < span.Length; index++) + { + if (span[index] > 0) + { + val += span[index]; + } + } + + return val; + } + + [BenchmarkCategory("BWSintArray.AsSpan"), Benchmark] + public int IntSpanWhereSumFast() + { + return Benchmarks.intArray.AsSpan().WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSintList"), Benchmark(Baseline = true)] + public int IntListWhereSumLinq() + { + return Benchmarks.intList.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSintList"), Benchmark] + public int IntListWhereSumFast() + { + return Benchmarks.intList.WhereSumF(x => x > 0); + } + + + [BenchmarkCategory("BWSintArraySelect"), Benchmark(Baseline = true)] + public int IntArrayWhereSumLinqSelect() + { + return Benchmarks.intArray.Where(x => x > 0).Sum(x => x / 2); + } + + [BenchmarkCategory("BWSintArraySelect"), Benchmark] + public int IntArrayWhereSumFastSelect() + { + return Benchmarks.intArray.WhereSumF(x => x > 0, x => x / 2); + } + + [BenchmarkCategory("BWSArray.AsReadOnlySelect"), Benchmark(Baseline = true)] + public double IntReadOnlyArraySumWithSelectLinq() + { + return Array.AsReadOnly(Benchmarks.intArray).Where(x => x > 0).Sum(x => x / 2); + } + + [BenchmarkCategory("BWSArray.AsReadOnlySelect"), Benchmark] + public double IntReadOnlyArraySumWithSelectFast() + { + return Array.AsReadOnly(Benchmarks.intArray).WhereSumF(x => x > 0, x => x / 2); + } + + + [BenchmarkCategory("BWSintNullArray"), Benchmark(Baseline = true)] + public int? IntNullArrayWhereSumLinq() + { + return Benchmarks.intNullArray.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSintNullArray"), Benchmark] + public int? IntNullArrayWhereSumFast() + { + return Benchmarks.intNullArray.WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSintNullArraySelect"), Benchmark(Baseline = true)] + public int IntNullArrayWhereSumLinqSelect() + { + return Benchmarks.intNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("BWSintNullArraySelect"), Benchmark] + public int IntNullArrayWhereSumFastSelect() + { + return Benchmarks.intNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + } + + [BenchmarkCategory("BWSfloatArray"), Benchmark(Baseline = true)] + public float FloatArrayWhereSumLinq() + { + return Benchmarks.floatArray.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSfloatArray"), Benchmark] + public float FloatArrayWhereSumFast() + { + return Benchmarks.floatArray.WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSfloatList"), Benchmark(Baseline = true)] + public float FloatListWhereSumLinq() + { + return Benchmarks.floatList.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSfloatList"), Benchmark] + public float FloatListWhereSumFast() + { + return Benchmarks.floatList.WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSfloatArraySelect"), Benchmark(Baseline = true)] + public float FloatArrayWhereSumLinqSelect() + { + return Benchmarks.floatArray.Where(x => x > 0).Sum(x => x / 2); + } + + [BenchmarkCategory("BWSfloatArraySelect"), Benchmark] + public float FloatArrayWhereSumFastSelect() + { + return Benchmarks.floatArray.WhereSumF(x => x > 0, x => x / 2); + } + + [BenchmarkCategory("BWSfloatNullArray"), Benchmark(Baseline = true)] + public float? FloatNullArrayWhereSumLinq() + { + return Benchmarks.floatNullArray.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSfloatNullArray"), Benchmark] + public float? FloatNullArrayWhereSumFast() + { + return Benchmarks.floatNullArray.WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSfloatNullArraySelect"), Benchmark(Baseline = true)] + public float FloatNullArrayWhereSumLinqSelect() + { + return Benchmarks.floatNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("BWSfloatNullArraySelect"), Benchmark] + public float FloatNullArrayWhereSumFastSelect() + { + return Benchmarks.floatNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + } + + + [BenchmarkCategory("BWSdoubleArray"), Benchmark(Baseline = true)] + public double DoubleArrayWhereSumLinq() + { + return Benchmarks.doubleArray.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSdoubleArray"), Benchmark] + public double DoubleArrayWhereSumFast() + { + return Benchmarks.doubleArray.WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSdoubleList"), Benchmark(Baseline = true)] + public double DoubleListWhereSumLinq() + { + return Benchmarks.doubleList.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSdoubleList"), Benchmark] + public double DoubleListWhereSumFast() + { + return Benchmarks.doubleList.WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSdoubleArraySelect"), Benchmark(Baseline = true)] + public double DoubleArrayWhereSumLinqSelect() + { + return Benchmarks.doubleArray.Where(x => x > 0).Sum(x => x / 2); + } + + [BenchmarkCategory("BWSdoubleArraySelect"), Benchmark] + public double DoubleArrayWhereSumFastSelect() + { + return Benchmarks.doubleArray.WhereSumF(x => x > 0, x => x / 2); + } + + [BenchmarkCategory("BWSdoubleNullArray"), Benchmark(Baseline = true)] + public double? DoubleNullArrayWhereSumLinq() + { + return Benchmarks.doubleNullArray.Where(x => x > 0).Sum(); + } + + [BenchmarkCategory("BWSdoubleNullArray"), Benchmark] + public double? DoubleNullArrayWhereSumFast() + { + return Benchmarks.doubleNullArray.WhereSumF(x => x > 0); + } + + [BenchmarkCategory("BWSdoubleNullArraySelect"), Benchmark(Baseline = true)] + public double? DoubleNullArrayWhereSumLinqSelect() + { + return Benchmarks.doubleNullArray.Where(x => x > 0).Sum(x => x / 2 ?? 0); + } + + [BenchmarkCategory("BWSdoubleNullArraySelect"), Benchmark] + public double? DoubleNullArrayWhereSumFastSelect() + { + return Benchmarks.doubleNullArray.WhereSumF(x => x > 0, x => x / 2 ?? 0); + } + + [BenchmarkCategory("BWSintListSelect"), Benchmark(Baseline = true)] + public int IntListSumWithSelectLinq() + { + return Benchmarks.intList.Where(x => x > 0).Sum(x => x / 2); + } + + [BenchmarkCategory("BWSintListSelect"), Benchmark] + public int IntListSumWithSelectFast() + { + return Benchmarks.intList.WhereSumF(x => x > 0, x => x / 2); + } + + [BenchmarkCategory("BWSintList.AsReadOnlySelect"), Benchmark(Baseline = true)] + public double IntReadOnlyListSumWithSelectLinq() + { + return Benchmarks.intList.AsReadOnly().Where(x => x > 0).Sum(x => x / 2); + } + + [BenchmarkCategory("BWSintList.AsReadOnlySelect"), Benchmark] + public double IntReadOnlyListSumWithSelectFast() + { + return Benchmarks.intList.AsReadOnly().WhereSumF(x => x > 0, x => x / 2); + } + + } +} diff --git a/Benchmarks/Benchmarks.cs b/Benchmarks/Benchmarks.cs index d3579b4..94fe581 100644 --- a/Benchmarks/Benchmarks.cs +++ b/Benchmarks/Benchmarks.cs @@ -1,238 +1,100 @@ using System; -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Running; -using JM.LinqFaster; -using JM.LinqFaster.Parallel; -using JM.LinqFaster.SIMD.Parallel; -using JM.LinqFaster.SIMD; - -using System.Linq; using System.Collections.Generic; + +using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Reports; +using BenchmarkDotNet.Running; namespace Tests { [MemoryDiagnoser] - public class Benchmarks + public partial class Benchmarks { - - const int LARGE_TEST_SIZE = 1000000; - const int SMALL_TEST_SIZE = 100; - - - - public List list; - public int[] array; - public int[] array2; - public float[] floatArray; - public string[] strarray; - - - [Params(1000000)] - public int TEST_SIZE { get; set; } - - public Benchmarks() - { - - - } - - [GlobalSetup] - public void Setup() - { - Random r = new Random(); - array = new int[TEST_SIZE]; + private const int LARGE_TEST_SIZE = 1000000; + private const int SMALL_TEST_SIZE = 100; + + internal static List list; + internal static byte[] byteArray; + internal static short[] shortArray; + internal static int[] intArray; + internal static List intList; + internal static int?[] intNullArray; + internal static int[] array2; + internal static float[] floatArray; + internal static List floatList; + internal static float?[] floatNullArray; + internal static double[] doubleArray; + internal static List doubleList; + internal static double?[] doubleNullArray; + internal static string[] strarray; + + + internal static int TEST_SIZE => LARGE_TEST_SIZE; + + static Benchmarks() + { + byteArray = new byte[TEST_SIZE]; + shortArray = new short[TEST_SIZE]; + intArray = new int[TEST_SIZE]; + intNullArray = new int?[TEST_SIZE]; + intList = new List(TEST_SIZE); array2 = new int[TEST_SIZE]; floatArray = new float[TEST_SIZE]; + floatList = new List(TEST_SIZE); + floatNullArray = new float?[TEST_SIZE]; + doubleArray = new double[TEST_SIZE]; + doubleList = new List(TEST_SIZE); + doubleNullArray = new double?[TEST_SIZE]; list = new List(TEST_SIZE); strarray = new string[TEST_SIZE]; - + for (int i = 0; i < TEST_SIZE; i++) { - array[i] = i % 2; + intArray[i] = i % 2; + byteArray[i] = (byte)intArray[i]; + shortArray[i] = (short)intArray[i]; + intNullArray[i] = intArray[i]; + intList.Add(intArray[i]); array2[i] = i % 2; - list.Add(array[i]); - strarray[i] = array[i].ToString(); - floatArray[i] = array[i]; + list.Add(intArray[i]); + strarray[i] = intArray[i].ToString(); + floatArray[i] = intArray[i]; + floatList.Add(floatArray[i]); + floatNullArray[i] = floatArray[i]; + doubleArray[i] = floatArray[i]; + doubleList.Add(doubleArray[i]); + doubleNullArray[i] = doubleArray[i]; } array2[TEST_SIZE / 2] = 0; } - /* - [Benchmark] - public int OrderByLinq() - { - return array.OrderBy((x => x -1)).Sum(); - } - - [Benchmark] - public int OrderByFast() - { - return array.OrderByF((x => x - 1)).Sum(); - } - - - - - [Benchmark] - public int SumLinq() - { - return array.Sum(); - } - - [Benchmark] - public int SumFast() - { - return array.SumF(); - } - - [Benchmark] - public int SumFastSIMD() - { - return array.SumS(); - } - - [Benchmark] - public double AverageLinq() - { - return array.Average(); - } - - [Benchmark] - public double AverageFast() - { - return array.AverageF(); - } - - [Benchmark] - public double AverageFastSIMD() - { - return array.AverageS(); - } - - [Benchmark] - public int SumWithSelectLinq() - { - return array.Sum(x => x / 2); - } - - [Benchmark] - public int SumWithSelectFast() - { - return array.SumF(x => x/2); - } - - - [Benchmark] - public double WhereAggregateLinq() - { - return array.Where(x => x % 2 == 0).Aggregate(0.0, (acc, x) => acc += x * x, acc => acc / array.Length); - } - - [Benchmark] - public double WhereAggregateFast() - { - return array.WhereAggregateF(x => x % 2 == 0,0.0,(acc,x)=> acc += x*x,acc => acc/array.Length); - } - - [Benchmark] - public int[] SelectFast() - { - return array.SelectF(x => x * x); - } - - [Benchmark] - public int[] SelectFastSIMD() - { - return array.SelectS(x => x * x, x=>x*x); - } - - - - [Benchmark] - public int[] RepeatLinq() - { - return Enumerable.Repeat(5, TEST_SIZE).ToArray(); - } - - [Benchmark] - public int[] RepeastFast() - { - return LinqFaster.RepeatArrayF(5, TEST_SIZE); - } - - - [Benchmark] - public int[] RepeastFastSIMD() - { - return LinqFasterSIMD.RepeatS(5, TEST_SIZE); - } - - [Benchmark] - public int[] RepeastFastSIMDB() - { - return LinqFasterSIMD.RepeatSB(5, TEST_SIZE); - } - - [Benchmark] - public int MinLinq() - { - return array.Min(); - } - - [Benchmark] - public int MinFast() - { - return array.MinF(); - } - - [Benchmark] - public int MinFastSIMD() - { - return array.MinS(); - } - - [Benchmark] - public bool SequenceEqual() - { - return array.SequenceEqual(array2); - }*/ - - [Benchmark] - public bool SequenceEqualF() - { - return array.SequenceEqualF(array2); - } - - - /* - [Benchmark] - public bool SequenceEqualP() - { - return array.SequenceEqualP(array2); - } - - [Benchmark] - public bool SequenceEqualS() - { - return array.SequenceEqualS(array2); - } - - [Benchmark] - public bool SequenceEqualSP() - { - return array.SequenceEqualSP(array2); - } - - */ - public static void Main(string[] args) { - - var summary = BenchmarkRunner.Run(ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64)); + ManualConfig config = (ManualConfig)ManualConfig.Create(DefaultConfig.Instance).With(Job.RyuJitX64); + config.Options |= ConfigOptions.JoinSummary; + + BenchmarkRunInfo[] benchmarkRunInfos = + { + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkSum), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksAverage), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksFirst), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksLast), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksMax), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksMin), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksAggregate), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksRepeat), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkOrderBy), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkSequenceEqual), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarkSelect), config), + BenchmarkConverter.TypeToBenchmarks(typeof (BenchmarksWhereAggregate), config), + //BenchmarkConverter.TypeToBenchmarks(typeof ( + }; + Summary[] summaries = BenchmarkRunner.Run(benchmarkRunInfos); + Console.WriteLine("Press enter to close"); Console.ReadLine(); } diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 4de8578..8835329 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -1,240 +1,255 @@  - - - - Debug - AnyCPU - {42DD1432-5209-49B3-81D7-B487A9DBF2F3} - Exe - Properties - Benchmarks - Benchmarks - v4.6.1 - 512 - true - - - - - - x64 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - x64 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - - - - ..\packages\BenchmarkDotNet.0.11.5\lib\netstandard2.0\BenchmarkDotNet.dll - - - ..\packages\BenchmarkDotNet.Annotations.0.11.5\lib\netstandard2.0\BenchmarkDotNet.Annotations.dll - - - ..\packages\CommandLineParser.2.5.0\lib\net461\CommandLine.dll - - - ..\packages\Microsoft.CodeAnalysis.Common.3.1.0\lib\netstandard2.0\Microsoft.CodeAnalysis.dll - - - ..\packages\Microsoft.CodeAnalysis.CSharp.3.1.0\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll - - - ..\packages\Microsoft.DotNet.InternalAbstractions.1.0.0\lib\net451\Microsoft.DotNet.InternalAbstractions.dll - - - ..\packages\Microsoft.DotNet.PlatformAbstractions.2.1.0\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll - - - ..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll - - - - ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll - - - ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll - - - ..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll - - - - ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll - True - True - - - - ..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll - True - True - - - ..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll - True - True - - - ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll - True - True - - - ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll - True - True - - - ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll - True - True - - - - ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll - - - - ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - - ..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll - - - ..\packages\System.Reflection.TypeExtensions.4.5.1\lib\net461\System.Reflection.TypeExtensions.dll - - - ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll - - - ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll - True - True - - - ..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll - - - ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll - True - True - - - ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll - True - True - - - ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll - True - True - - - ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll - True - True - - - ..\packages\System.Security.Principal.Windows.4.5.1\lib\net461\System.Security.Principal.Windows.dll - - - ..\packages\System.Text.Encoding.CodePages.4.5.1\lib\net461\System.Text.Encoding.CodePages.dll - - - ..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll - - - ..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll - True - True - - - ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll - - - - - - - - - ..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll - True - True - - - ..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll - True - True - - - ..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll - True - True - - - ..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll - True - True - - - ..\packages\System.Xml.XPath.XmlDocument.4.3.0\lib\net46\System.Xml.XPath.XmlDocument.dll - - - - - - - - - - - - - {f13bac10-bcbe-4440-b9f0-3a2778ca9221} - LinqFasterParallelSIMD - - - {1b6d88e4-8745-4a0e-b459-53f7add04a12} - LinqFasterParallel - - - {050c43b5-4a4f-45d9-be0c-9b2a6acc189e} - LinqFasterSIMD - - - {5b2f0f9f-6dda-4f06-a999-26e43ae04f86} - LinqFaster - - - - - - - - + + - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + Debug + AnyCPU + {42DD1432-5209-49B3-81D7-B487A9DBF2F3} + Exe + Properties + Tests + Benchmarks + v4.6.1 + 512 + true + + + - - -