rspec/rules/S6602/resources-dotnet.adoc
Martin Strecker 823fcb14f6
Modify rule S6602: Update benchmark (#4438)
* 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>
2024-10-29 12:33:52 +01:00

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&lt;T&gt; | 83.796 μs | 1.3199 μs | 72 B
| ImmutableListFind | .NET 8.0 | ImmutableList&lt;T&gt; | 59.720 μs | 1.0723 μs | -
| | | | | |
| ImmutableListFirstOrDefault | .NET 9.0 | ImmutableList&lt;T&gt; | 81.984 μs | 1.0886 μs | 72 B
| ImmutableListFind | .NET 9.0 | ImmutableList&lt;T&gt; | 58.288 μs | 0.8079 μs | -
| | | | | |
| ImmutableListFirstOrDefault | .NET Framework 4.8.1 | ImmutableList&lt;T&gt; | 446.893 μs | 9.8430 μs | 76 B
| ImmutableListFind | .NET Framework 4.8.1 | ImmutableList&lt;T&gt; | 427.476 μs | 3.3371 μs | -
| | | | | |
| ListFirstOrDefault | .NET 8.0 | List&lt;T&gt; | 14.808 μs | 0.1723 μs | 40 B
| ListFind | .NET 8.0 | List&lt;T&gt; | 6.040 μs | 0.1104 μs | -
| | | | | |
| ListFirstOrDefault | .NET 9.0 | List&lt;T&gt; | 2.233 μs | 0.0154 μs | -
| ListFind | .NET 9.0 | List&lt;T&gt; | 4.458 μs | 0.0745 μs | -
| | | | | |
| ListFirstOrDefault | .NET Framework 4.8.1 | List&lt;T&gt; | 57.290 μs | 1.0494 μs | 40 B
| ListFind | .NET Framework 4.8.1 | List&lt;T&gt; | 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
----