
* Update benchmark * Update why-dotnet.adoc * Remove from SonarWay * Apply suggestions from code review Co-authored-by: Cristian <67206480+CristianAmbrosini@users.noreply.github.com> --------- Co-authored-by: Cristian <67206480+CristianAmbrosini@users.noreply.github.com>
105 lines
5.6 KiB
Plaintext
105 lines
5.6 KiB
Plaintext
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.find[List<T>.Find(Predicate<T>)]
|
|
* https://learn.microsoft.com/en-us/dotnet/api/system.array.find[Array.Find<T>(T[\], Predicate<T>)]
|
|
* https://learn.microsoft.com/en-us/dotnet/api/system.collections.immutable.immutablelist-1.find[ImmutableList<T>.Find(Predicate<T>)]
|
|
* https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.firstordefault[Enumerable.FirstOrDefault(Predicate<T>)]
|
|
|
|
=== Benchmarks
|
|
|
|
[options="header"]
|
|
|===
|
|
| Method | Runtime | Categories | Mean | Standard Deviation | Allocated
|
|
| ArrayFirstOrDefault | .NET 8.0 | Array | 10.515 μs | 0.1410 μs | 32 B
|
|
| ArrayFind | .NET 8.0 | Array | 4.417 μs | 0.0729 μs | -
|
|
| | | | | |
|
|
| ArrayFirstOrDefault | .NET 9.0 | Array | 2.262 μs | 0.0135 μs | -
|
|
| ArrayFind | .NET 9.0 | Array | 3.428 μs | 0.0206 μs | -
|
|
| | | | | |
|
|
| ArrayFirstOrDefault | .NET Framework 4.8.1 | Array | 45.074 μs | 0.7517 μs | 32 B
|
|
| ArrayFind | .NET Framework 4.8.1 | Array | 13.948 μs | 0.1496 μs | -
|
|
| | | | | |
|
|
| ImmutableListFirstOrDefault | .NET 8.0 | ImmutableList<T> | 83.796 μs | 1.3199 μs | 72 B
|
|
| ImmutableListFind | .NET 8.0 | ImmutableList<T> | 59.720 μs | 1.0723 μs | -
|
|
| | | | | |
|
|
| ImmutableListFirstOrDefault | .NET 9.0 | ImmutableList<T> | 81.984 μs | 1.0886 μs | 72 B
|
|
| ImmutableListFind | .NET 9.0 | ImmutableList<T> | 58.288 μs | 0.8079 μs | -
|
|
| | | | | |
|
|
| ImmutableListFirstOrDefault | .NET Framework 4.8.1 | ImmutableList<T> | 446.893 μs | 9.8430 μs | 76 B
|
|
| ImmutableListFind | .NET Framework 4.8.1 | ImmutableList<T> | 427.476 μs | 3.3371 μs | -
|
|
| | | | | |
|
|
| ListFirstOrDefault | .NET 8.0 | List<T> | 14.808 μs | 0.1723 μs | 40 B
|
|
| ListFind | .NET 8.0 | List<T> | 6.040 μs | 0.1104 μs | -
|
|
| | | | | |
|
|
| ListFirstOrDefault | .NET 9.0 | List<T> | 2.233 μs | 0.0154 μs | -
|
|
| ListFind | .NET 9.0 | List<T> | 4.458 μs | 0.0745 μs | -
|
|
| | | | | |
|
|
| ListFirstOrDefault | .NET Framework 4.8.1 | List<T> | 57.290 μs | 1.0494 μs | 40 B
|
|
| ListFind | .NET Framework 4.8.1 | List<T> | 18.476 μs | 0.0504 μs | -
|
|
|===
|
|
|
|
==== Glossary
|
|
|
|
* https://en.wikipedia.org/wiki/Arithmetic_mean[Mean]
|
|
* https://en.wikipedia.org/wiki/Standard_deviation[Standard Deviation]
|
|
* https://en.wikipedia.org/wiki/Memory_management[Allocated]
|
|
|
|
The results were generated by running the following snippet with https://github.com/dotnet/BenchmarkDotNet[BenchmarkDotNet]:
|
|
|
|
[source,csharp]
|
|
----
|
|
// Explicitly cache the delegates to avoid allocations inside the benchmark.
|
|
private readonly static Func<int, bool> ConditionFunc = static x => x == 1;
|
|
private readonly static Predicate<int> ConditionPredicate = static x => x == 1;
|
|
private List<int> list;
|
|
private ImmutableList<int> immutableList;
|
|
private int[] array;
|
|
public const int N = 10_000;
|
|
|
|
[GlobalSetup]
|
|
public void GlobalSetup()
|
|
{
|
|
list = Enumerable.Range(0, N).Select(x => N - x).ToList();
|
|
immutableList = ImmutableList.CreateRange(list);
|
|
array = list.ToArray();
|
|
}
|
|
|
|
[BenchmarkCategory("List<T>"), Benchmark(Baseline = true)]
|
|
public int ListFirstOrDefault() =>
|
|
list.FirstOrDefault(ConditionFunc);
|
|
|
|
[BenchmarkCategory("List<T>"), Benchmark]
|
|
public int ListFind() =>
|
|
list.Find(ConditionPredicate);
|
|
|
|
[BenchmarkCategory("ImmutableList<T>"), Benchmark(Baseline = true)]
|
|
public int ImmutableListFirstOrDefault() =>
|
|
immutableList.FirstOrDefault(ConditionFunc);
|
|
|
|
[BenchmarkCategory("ImmutableList<T>"), Benchmark]
|
|
public int ImmutableListFind() =>
|
|
immutableList.Find(ConditionPredicate);
|
|
|
|
[BenchmarkCategory("Array"), Benchmark(Baseline = true)]
|
|
public int ArrayFirstOrDefault() =>
|
|
array.FirstOrDefault(ConditionFunc);
|
|
|
|
[BenchmarkCategory("Array"), Benchmark]
|
|
public int ArrayFind() =>
|
|
Array.Find(array, ConditionPredicate);
|
|
----
|
|
|
|
Hardware configuration:
|
|
|
|
[source]
|
|
----
|
|
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4317/23H2/2023Update/SunValley3)
|
|
11th Gen Intel Core i7-11850H 2.50GHz, 1 CPU, 16 logical and 8 physical cores
|
|
[Host] : .NET Framework 4.8.1 (4.8.9277.0), X64 RyuJIT VectorSize=256
|
|
.NET 8.0 : .NET 8.0.10 (8.0.1024.46610), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
|
|
.NET 9.0 : .NET 9.0.0 (9.0.24.47305), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
|
|
.NET Framework 4.8.1 : .NET Framework 4.8.1 (4.8.9277.0), X64 RyuJIT VectorSize=256
|
|
----
|