Skip to content

Instantly share code, notes, and snippets.

@MichalBrylka
Last active February 6, 2023 22:17
Show Gist options
  • Save MichalBrylka/c0735a0ab1b360dba93ae3a3cc014ccd to your computer and use it in GitHub Desktop.
Save MichalBrylka/c0735a0ab1b360dba93ae3a3cc014ccd to your computer and use it in GitHub Desktop.
LINQ benchmarks

BenchmarkDotNet=v0.13.3, OS=Windows 10 (10.0.19044.2486/21H2/November2021Update) Intel Core i7-8700 CPU 3.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores .NET SDK=7.0.100 [Host] : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2 DefaultJob : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2

Linq_WhereAndFirst_Vs_First

Method Size Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
WhereAndFirst_Array 10 47.85 ns 0.975 ns 1.301 ns baseline 0.0216 136 B
First_Array 10 54.37 ns 0.243 ns 0.203 ns +15% 2.7% 0.0191 120 B -12%
WhereAndFirst_Enumerable 10 93.61 ns 1.621 ns 1.437 ns baseline 0.0293 184 B
First_Enumerable 10 63.95 ns 1.240 ns 1.273 ns -32% 3.0% 0.0204 128 B -30%
WhereAndFirst_Array 100 120.60 ns 1.067 ns 0.945 ns baseline 0.0215 136 B
First_Array 100 293.09 ns 1.261 ns 1.180 ns +143% 0.8% 0.0191 120 B -12%
WhereAndFirst_Enumerable 100 354.49 ns 4.052 ns 3.790 ns baseline 0.0291 184 B
First_Enumerable 100 332.65 ns 1.550 ns 1.294 ns -6% 1.1% 0.0200 128 B -30%

Linq_Count_Vs_Any

Method Size Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
Count_Array 10 8.012 ns 0.0932 ns 0.0872 ns baseline - - NA
Any_Array 10 8.714 ns 0.0505 ns 0.0472 ns +9% 1.2% - - NA
Count_Enumerable 10 49.501 ns 0.3702 ns 0.3282 ns baseline 0.0063 40 B
Any_Enumerable 10 19.042 ns 0.0860 ns 0.0763 ns -62% 0.7% 0.0063 40 B +0%
Count_Array 100 8.632 ns 0.0676 ns 0.0633 ns baseline - - NA
Any_Array 100 8.064 ns 0.0697 ns 0.0582 ns -7% 0.7% - - NA
Count_Enumerable 100 289.673 ns 4.8053 ns 4.2598 ns baseline 0.0062 40 B
Any_Enumerable 100 19.083 ns 0.1910 ns 0.1693 ns -93% 1.7% 0.0063 40 B +0%

Linq_Count_Vs_Any_WithPredicate

Method Size Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
Iterate_Array 10 3.764 ns 0.0494 ns 0.0438 ns baseline - - NA
Count_Array 10 75.808 ns 0.5585 ns 0.5224 ns +1,912% 1.0% 0.0191 120 B NA
Any_Array 10 56.647 ns 0.6287 ns 0.4909 ns +1,405% 1.3% 0.0191 120 B NA
Iterate_Enumerable 10 41.854 ns 0.3089 ns 0.2739 ns baseline 0.0063 40 B
Count_Enumerable 10 82.023 ns 0.3597 ns 0.3365 ns +96% 0.7% 0.0204 128 B +220%
Any_Enumerable 10 58.203 ns 0.3344 ns 0.2964 ns +39% 0.8% 0.0204 128 B +220%
Iterate_Array 100 25.661 ns 0.1365 ns 0.1277 ns baseline - - NA
Count_Array 100 559.625 ns 3.3309 ns 2.9528 ns +2,082% 0.7% 0.0191 120 B NA
Any_Array 100 309.281 ns 1.5064 ns 1.2579 ns +1,107% 0.6% 0.0191 120 B NA
Iterate_Enumerable 100 240.658 ns 1.6646 ns 1.4757 ns baseline 0.0062 40 B
Count_Enumerable 100 608.032 ns 3.2091 ns 3.0018 ns +153% 0.7% 0.0200 128 B +220%
Any_Enumerable 100 309.636 ns 2.7584 ns 2.5802 ns +29% 0.9% 0.0200 128 B +220%
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" />
</ItemGroup>
</Project>
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Reports;
namespace Benchmarks;
/*BenchmarkDotNet=v0.13.3, OS=Windows 10 (10.0.19044.2486/21H2/November2021Update)
Intel Core i7-8700 CPU 3.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK=7.0.100
[Host] : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2
DefaultJob : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2
| Method | Size | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|----------------- |----- |-----------:|----------:|----------:|---------:|--------:|-------:|----------:|------------:|
| Count_Array | 10 | 8.012 ns | 0.0932 ns | 0.0872 ns | baseline | | - | - | NA |
| Any_Array | 10 | 8.714 ns | 0.0505 ns | 0.0472 ns | +9% | 1.2% | - | - | NA |
| | | | | | | | | | |
| Count_Enumerable | 10 | 49.501 ns | 0.3702 ns | 0.3282 ns | baseline | | 0.0063 | 40 B | |
| Any_Enumerable | 10 | 19.042 ns | 0.0860 ns | 0.0763 ns | -62% | 0.7% | 0.0063 | 40 B | +0% |
| | | | | | | | | | |
| | | | | | | | | | |
| Count_Array | 100 | 8.632 ns | 0.0676 ns | 0.0633 ns | baseline | | - | - | NA |
| Any_Array | 100 | 8.064 ns | 0.0697 ns | 0.0582 ns | -7% | 0.7% | - | - | NA |
| | | | | | | | | | |
| Count_Enumerable | 100 | 289.673 ns | 4.8053 ns | 4.2598 ns | baseline | | 0.0062 | 40 B | |
| Any_Enumerable | 100 | 19.083 ns | 0.1910 ns | 0.1693 ns | -93% | 1.7% | 0.0063 | 40 B | +0% |
*/
[MemoryDiagnoser]
//[SimpleJob(RuntimeMoniker.Net70)]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[Config(typeof(Config))]
public class Linq_Count_Vs_Any
{
private class Config : ManualConfig
{
public Config() =>
SummaryStyle = SummaryStyle.Default.WithRatioStyle(RatioStyle.Percentage);
}
private int[] _data;
[Params(10, 100)]
public int Size { get; set; }
[GlobalSetup]
public void Setup() => _data = Enumerable.Range(0, Size).ToArray();
private IEnumerable<int> GetEnumerable()
{
for (int i = 0; i < _data.Length; i++)
yield return _data[i];
}
[BenchmarkCategory("Array"), Benchmark(Baseline = true)]
public bool Count_Array() => _data.Count() > 0;
[BenchmarkCategory("Array"), Benchmark]
public bool Any_Array() => _data.Any();
[BenchmarkCategory("Enumerable"), Benchmark(Baseline = true)]
public bool Count_Enumerable() => GetEnumerable().Count() > 0;
[BenchmarkCategory("Enumerable"), Benchmark]
public bool Any_Enumerable() => GetEnumerable().Any();
}
/*
| Method | Size | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------- |----- |-----------:|----------:|----------:|---------:|--------:|-------:|----------:|------------:|
| Iterate_Array | 10 | 3.764 ns | 0.0494 ns | 0.0438 ns | baseline | | - | - | NA |
| Count_Array | 10 | 75.808 ns | 0.5585 ns | 0.5224 ns | +1,912% | 1.0% | 0.0191 | 120 B | NA |
| Any_Array | 10 | 56.647 ns | 0.6287 ns | 0.4909 ns | +1,405% | 1.3% | 0.0191 | 120 B | NA |
| | | | | | | | | | |
| Iterate_Enumerable | 10 | 41.854 ns | 0.3089 ns | 0.2739 ns | baseline | | 0.0063 | 40 B | |
| Count_Enumerable | 10 | 82.023 ns | 0.3597 ns | 0.3365 ns | +96% | 0.7% | 0.0204 | 128 B | +220% |
| Any_Enumerable | 10 | 58.203 ns | 0.3344 ns | 0.2964 ns | +39% | 0.8% | 0.0204 | 128 B | +220% |
| | | | | | | | | | |
| | | | | | | | | | |
| Iterate_Array | 100 | 25.661 ns | 0.1365 ns | 0.1277 ns | baseline | | - | - | NA |
| Count_Array | 100 | 559.625 ns | 3.3309 ns | 2.9528 ns | +2,082% | 0.7% | 0.0191 | 120 B | NA |
| Any_Array | 100 | 309.281 ns | 1.5064 ns | 1.2579 ns | +1,107% | 0.6% | 0.0191 | 120 B | NA |
| | | | | | | | | | |
| Iterate_Enumerable | 100 | 240.658 ns | 1.6646 ns | 1.4757 ns | baseline | | 0.0062 | 40 B | |
| Count_Enumerable | 100 | 608.032 ns | 3.2091 ns | 3.0018 ns | +153% | 0.7% | 0.0200 | 128 B | +220% |
| Any_Enumerable | 100 | 309.636 ns | 2.7584 ns | 2.5802 ns | +29% | 0.9% | 0.0200 | 128 B | +220% |
*/
[MemoryDiagnoser]
//[SimpleJob(RuntimeMoniker.Net70)]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[Config(typeof(Config))]
public class Linq_Count_Vs_Any_WithPredicate
{
private class Config : ManualConfig
{
public Config() =>
SummaryStyle = SummaryStyle.Default.WithRatioStyle(RatioStyle.Percentage);
}
private int[] _data;
[Params(10, 100)]
public int Size { get; set; }
[GlobalSetup]
public void Setup() => _data = Enumerable.Range(0, Size).ToArray();
private IEnumerable<int> GetEnumerable()
{
for (int i = 0; i < _data.Length; i++)
yield return _data[i];
}
[BenchmarkCategory("Array"), Benchmark(Baseline = true)]
public bool Iterate_Array()
{
var midPoint = Size / 2;
for (int i = 0; i < _data.Length; i++)
{
if (_data[i] > midPoint)
return true;
}
return false;
}
[BenchmarkCategory("Array"), Benchmark]
public bool Count_Array()
{
var midPoint = Size / 2;
return _data.Count(i => i > midPoint) > 0;
}
[BenchmarkCategory("Array"), Benchmark]
public bool Any_Array()
{
var midPoint = Size / 2;
return _data.Any(i => i > midPoint);
}
[BenchmarkCategory("Enumerable"), Benchmark(Baseline = true)]
public bool Iterate_Enumerable()
{
var midPoint = Size / 2;
foreach (var item in GetEnumerable())
{
if (item > midPoint)
return true;
}
return false;
}
[BenchmarkCategory("Enumerable"), Benchmark]
public bool Count_Enumerable()
{
var midPoint = Size / 2;
return GetEnumerable().Count(i => i > midPoint) > 0;
}
[BenchmarkCategory("Enumerable"), Benchmark]
public bool Any_Enumerable()
{
var midPoint = Size / 2;
return GetEnumerable().Any(i => i > midPoint);
}
}
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Reports;
namespace Benchmarks;
/*BenchmarkDotNet=v0.13.3, OS=Windows 10 (10.0.19044.2486/21H2/November2021Update)
Intel Core i7-8700 CPU 3.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK=7.0.100
[Host] : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2
DefaultJob : .NET 6.0.13 (6.0.1322.58009), X64 RyuJIT AVX2
| Method | Size | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------------- |----- |----------:|---------:|---------:|---------:|--------:|-------:|----------:|------------:|
| WhereAndFirst_Array | 10 | 47.85 ns | 0.975 ns | 1.301 ns | baseline | | 0.0216 | 136 B | |
| First_Array | 10 | 54.37 ns | 0.243 ns | 0.203 ns | +15% | 2.7% | 0.0191 | 120 B | -12% |
| | | | | | | | | | |
| WhereAndFirst_Enumerable | 10 | 93.61 ns | 1.621 ns | 1.437 ns | baseline | | 0.0293 | 184 B | |
| First_Enumerable | 10 | 63.95 ns | 1.240 ns | 1.273 ns | -32% | 3.0% | 0.0204 | 128 B | -30% |
| | | | | | | | | | |
| | | | | | | | | | |
| WhereAndFirst_Array | 100 | 120.60 ns | 1.067 ns | 0.945 ns | baseline | | 0.0215 | 136 B | |
| First_Array | 100 | 293.09 ns | 1.261 ns | 1.180 ns | +143% | 0.8% | 0.0191 | 120 B | -12% |
| | | | | | | | | | |
| WhereAndFirst_Enumerable | 100 | 354.49 ns | 4.052 ns | 3.790 ns | baseline | | 0.0291 | 184 B | |
| First_Enumerable | 100 | 332.65 ns | 1.550 ns | 1.294 ns | -6% | 1.1% | 0.0200 | 128 B | -30% |*/
[MemoryDiagnoser]
//[SimpleJob(RuntimeMoniker.Net70)]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[Config(typeof(Config))]
public class Linq_WhereAndFirst_Vs_First
{
private class Config : ManualConfig
{
public Config() =>
SummaryStyle = SummaryStyle.Default.WithRatioStyle(RatioStyle.Percentage);
}
private int[] _data;
[Params(10, 100)]
public int Size { get; set; }
[GlobalSetup]
public void Setup() => _data = Enumerable.Range(0, Size).ToArray();
private IEnumerable<int> GetEnumerable()
{
for (int i = 0; i < _data.Length; i++)
yield return _data[i];
}
[BenchmarkCategory("Array"), Benchmark(Baseline = true)]
public int WhereAndFirst_Array()
{
var midPoint = Size / 2;
return _data.Where(i => i > midPoint).First();
}
[BenchmarkCategory("Array"), Benchmark]
public int First_Array()
{
var midPoint = Size / 2;
return _data.First(i => i > midPoint);
}
[BenchmarkCategory("Enumerable"), Benchmark(Baseline = true)]
public int WhereAndFirst_Enumerable()
{
var midPoint = Size / 2;
return GetEnumerable().Where(i => i > midPoint).First();
}
[BenchmarkCategory("Enumerable"), Benchmark]
public int First_Enumerable()
{
var midPoint = Size / 2;
return GetEnumerable().First(i => i > midPoint);
}
}
using BenchmarkDotNet.Running;
namespace Benchmarks;
internal class Program
{
private static void Main(string[] args) =>
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment