Three different implementations of finding the sum of an IEnumerable < int> source are given below along with the time taken when the source has 10,000 integ
Only a decade late, but...
I've worked on a Linq replacement (nuget, github), which is (mostly!) a drop in replacement for System.Linq (just by adding the nuget package and then changing using System.Linq
to using Cistern.ValueLinq
) but using value types and some tricks under the hood.
Anyway, as far as Sum
goes, it uses SIMD instructions under the hood (still honouring overflow) where it can.
Results below are running on a machine which is old as this original stackoverflow question, so modern machines should even have better results (although for a non SIMD able IEnumerable you do are getting some overhead)
public enum ContainerTypes { Enumerable, Array, List, }
[MemoryDiagnoser]
public class Benchmarks
{
IEnumerable _data;
[Params(ContainerTypes.Array, ContainerTypes.Enumerable, ContainerTypes.List)]
public ContainerTypes ContainerType { get; set; } = ContainerTypes.Enumerable;
[GlobalSetup]
public void SetupData()
{
var data = System.Linq.Enumerable.Range(0, 1000);
_data = ContainerType switch
{
ContainerTypes.Enumerable => data,
ContainerTypes.Array => System.Linq.Enumerable.ToArray(data),
ContainerTypes.List => System.Linq.Enumerable.ToList(data),
_ => throw new Exception("Unknown ContainerType")
};
}
[Benchmark(Baseline = true)] public int System_Linq_Sum() => System.Linq.Enumerable.Sum(_data);
[Benchmark] public int System_Linq_Sum_Predicate() => System.Linq.Enumerable.Sum(_data, c => c);
[Benchmark] public int System_Linq_Aggregate() => System.Linq.Enumerable.Aggregate(_data, 0, (result, element) => result + element);
[Benchmark] public int Cistern_ValueLinq_Sum() => Cistern.ValueLinq.Enumerable.Sum(_data);
[Benchmark] public int Cistern_ValueLinq_Sum_Predicate() => Cistern.ValueLinq.Enumerable.Sum(_data, c => c);
[Benchmark] public int Cistern_ValueLinq_Aggregate() => Cistern.ValueLinq.Enumerable.Aggregate(_data, 0, (result, element) => result + element);
static void Main(string[] args) => BenchmarkRunner.Run();
}
Method | ContainerType | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
---|---|---|---|---|---|---|---|---|---|---|---|
System_Linq_Sum | Enumerable | 6.025 us | 0.1155 us | 0.1501 us | 6.041 us | 1.00 | 0.00 | 0.0076 | - | - | 40 B |
System_Linq_Sum_Predicate | Enumerable | 8.731 us | 0.1727 us | 0.3681 us | 8.742 us | 1.45 | 0.08 | - | - | - | 40 B |
System_Linq_Aggregate | Enumerable | 8.534 us | 0.1683 us | 0.3514 us | 8.657 us | 1.42 | 0.07 | - | - | - | 40 B |
Cistern_ValueLinq_Sum | Enumerable | 6.907 us | 0.1369 us | 0.3061 us | 6.911 us | 1.15 | 0.07 | 0.0076 | - | - | 40 B |
Cistern_ValueLinq_Sum_Predicate | Enumerable | 9.769 us | 0.1907 us | 0.1784 us | 9.823 us | 1.62 | 0.04 | - | - | - | 40 B |
Cistern_ValueLinq_Aggregate | Enumerable | 9.295 us | 0.1847 us | 0.4962 us | 9.396 us | 1.52 | 0.08 | - | - | - | 40 B |
System_Linq_Sum | Array | 6.731 us | 0.1343 us | 0.3653 us | 6.814 us | 1.00 | 0.00 | 0.0076 | - | - | 32 B |
System_Linq_Sum_Predicate | Array | 9.432 us | 0.1873 us | 0.5065 us | 9.685 us | 1.41 | 0.11 | - | - | - | 32 B |
System_Linq_Aggregate | Array | 9.494 us | 0.1890 us | 0.4707 us | 9.759 us | 1.41 | 0.11 | - | - | - | 32 B |
Cistern_ValueLinq_Sum | Array | 1.404 us | 0.0279 us | 0.0710 us | 1.436 us | 0.21 | 0.02 | - | - | - | - |
Cistern_ValueLinq_Sum_Predicate | Array | 4.064 us | 0.0811 us | 0.0996 us | 4.087 us | 0.61 | 0.04 | - | - | - | - |
Cistern_ValueLinq_Aggregate | Array | 3.549 us | 0.0709 us | 0.1496 us | 3.584 us | 0.53 | 0.04 | - | - | - | - |
System_Linq_Sum | List | 11.779 us | 0.2344 us | 0.3048 us | 11.854 us | 1.00 | 0.00 | - | - | - | 40 B |
System_Linq_Sum_Predicate | List | 14.227 us | 0.2842 us | 0.6919 us | 14.601 us | 1.22 | 0.05 | - | - | - | 40 B |
System_Linq_Aggregate | List | 13.852 us | 0.2761 us | 0.7418 us | 14.249 us | 1.17 | 0.06 | - | - | - | 40 B |
Cistern_ValueLinq_Sum | List | 1.437 us | 0.0288 us | 0.0835 us | 1.471 us | 0.12 | 0.01 | - | - | - | - |
Cistern_ValueLinq_Sum_Predicate | List | 3.672 us | 0.0732 us | 0.1941 us | 3.771 us | 0.32 | 0.02 | - | - | - | - |
Cistern_ValueLinq_Aggregate | List | 3.597 us | 0.0718 us | 0.1880 us | 3.698 us | 0.31 | 0.02 | - | - | - | - |