Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- Convert SumF functions for Array, Span, and List into a generic function #20

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
666f1fa
- Convert SumF function into a generic function
Jul 30, 2019
cf405ac
SumF for an Array
Jul 31, 2019
4eb6b16
- Split the Sum types out
Jul 31, 2019
71459b2
- Fix float selector special case
Jul 31, 2019
8ee3849
[Enhancement] Can these API's also work on IList<T> #15
Jul 31, 2019
cb6ce9d
- Add Nullable types for List and IList
Jul 31, 2019
d6a2542
- Use "IList fast redirect" to implement all average Base and Nullabl…
Jul 31, 2019
3ecde38
- Complete base types applicable to Span<T>
Jul 31, 2019
e93f373
Fix #21: [Bug] `Span SumF` is slower than a for loop over a span
Aug 1, 2019
fed5794
[Enhancement] Can these API's also work on IList<T> #15
Aug 1, 2019
d3b706e
[Enhancement] Can these API's also work on IList<T> #15
Aug 1, 2019
1e464b9
Investigate #22: [Question] Span_FirstF and List_First are slower tha…
Aug 2, 2019
81c2a40
Investigate #22: [Question] Span_FirstF and List_FirstF are slower th…
Aug 2, 2019
b762eff
Investigate #15: [Enhancement] Can these API's also work on IReadOnly…
Aug 5, 2019
ac38801
More for #15: [Enhancement] Can these API's also work on IReadOnlyLis…
Aug 5, 2019
57932a1
Initial commit for #24: [Enhancement] DefaultIfEmptyF should be imple…
Aug 5, 2019
c7652e0
MaxF's for #15 : [Enhancement] Can these API's also work on IReadOnl…
Aug 6, 2019
54e72fa
MinF's for #15 : [Enhancement] Can these API's also work on IReadOnl…
Aug 6, 2019
c3669bf
WhereSumF's for #15 : [Enhancement] Can these API's also work on IRe…
Aug 6, 2019
ce954e2
- Note: Lists can have items added and removed whilst these API's are…
Aug 6, 2019
3bafae3
Invesigate #25: [Enhancement] Please also target .net4.8 and Benchmark
Aug 7, 2019
9c9dd9d
Investigate #25: [Enhancement] Please also target .net4.8 and Benchmark
Aug 7, 2019
fb43c8c
Investigate #21: [Bug] Span SumF is slower than a for loop over a span
Aug 8, 2019
25c68fc
- Attempt to fic AppVeyor
Aug 8, 2019
064760c
- Another Attempt to satisfy Appveyor
Aug 8, 2019
66e84c4
- Appveyor again - Reset the bindingRedirects
Aug 8, 2019
1963489
- Look Apveyor Use the correct system.memry version will ya !
Aug 8, 2019
37f256c
- (Maybe) Seems like the App.config is being ignored, so be explicit …
Aug 8, 2019
5927bcb
- Fix weird "Sometimes failing" test that show aggressive inlining do…
Aug 8, 2019
5db00ad
- test the unit Test Again !
Aug 8, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
110 changes: 25 additions & 85 deletions Benchmarks/App.config
Original file line number Diff line number Diff line change
@@ -1,90 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<runtime>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoiding these kind of whitespace changes can help focus the review and speed up the review. In addition, it helps reviewers to stay focused so they can more likely catch issues

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.ReaderWriter" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="BenchmarkDotNet.Core" publicKeyToken="aa0ca2f9092cefc4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.10.14.0" newVersion="0.10.14.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.DotNet.PlatformAbstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
95 changes: 95 additions & 0 deletions Benchmarks/BenchmarkAggregate.cs
Original file line number Diff line number Diff line change
@@ -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<double, int, double> 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);
}
}
}
53 changes: 53 additions & 0 deletions Benchmarks/BenchmarkAverage.cs
Original file line number Diff line number Diff line change
@@ -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();
//}

}
}
98 changes: 98 additions & 0 deletions Benchmarks/BenchmarkFirst.cs
Original file line number Diff line number Diff line change
@@ -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<int, bool> firstInts = (x) => x > 0;

[BenchmarkCategory("BFintArray"), Benchmark(Baseline = true)]
public double IntArrayFirstLinqSelector()
{
return Benchmarks.intArray.First(firstInts);
}

[BenchmarkCategory("BFintArray"), Benchmark]
public double IntArrayFirstArrayFindSelector()
{
Predicate<int> predicate = new Predicate<int>(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<int> 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<int> 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);
}

}
}