Sometimes, you just need to check whether a collection is empty or null to skip execution. But how expensive is that?
This very simple benchmark tested some ways to do this:
AntonioFalcaoJr / Benchmark
Sometimes, you just need to check whether a collection is empty or null to skip execution. But how expensive is that?
Scenarios
// SCENARIO 1
var list = Ids?.ToList() ?? new List<Guid>();
if (list.Any() is false) { }
// SCENARIO 2
var list = Ids?.ToArray() ?? Array.Empty<Guid>();
if (list.Any() is false) { }
// SCENARIO 3
// toList();
var list = _ids?.ToList();
if (list is null || list.Any() is false) { }
// toArray();
var list = _ids?.ToArray();
if (list is null || list.Any() is false) { }
// SCENARIO 4
// toList();
var list = Ids?.ToList();
if (list is {Count: > 0} is false) { }
// toArray();
var list = _ids?.ToArray();
if (list is {Length: > 0} is false) { }
// SCENARIO 5
// toList();
var list = Ids?.ToList();
if (list?.Count <= 0) { }
// toArray();
var list = _ids?.ToArray();
if (list?.Length <= 0) { }
Result
BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1198 (1909/November2018Update/19H2)
Intel Core i7-9700 CPU 3.00GHz, 1 CPU, 8 logical and 8 physical cores
.NET Core SDK=5.0.101
[Host] : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT
.NET Core 3.1 : .NET Core 3.1.10 (CoreCLR 4.700.20.51601, CoreFX 4.700.20.51901), X64 RyuJIT
.NET Core 5.0 : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT
Method | Runtime | Mean | Error | StdDev | Ratio | RatioSD |
---|---|---|---|---|---|---|
Scenario1 | Core 3.1 | 25.0384ns | 0.5082ns | 0.5649ns | 2.64 | 0.06 |
Scenario1 | .NET Core 5.0 | 9.5186ns | 0.1186ns | 0.1109ns | 1.00 | 0.00 |
Scenario2 | Core 3.1 | 7.0908ns | 0.0687ns | 0.0537ns | 0.63 | 0.00 |
Scenario2 | .NET 5 | 11.2512ns | 0.0510ns | 0.0426ns | 1.00 | 0.00 |
Scenario3 toList | Core 3.1 | 0.4756ns | 0.0099ns | 0.0093ns | 0.85 | 0.04 |
Scenario3 toList | .NET 5 | 0.5622ns | 0.0278ns | 0.0246ns | 1.00 | 0.00 |
Scenario3 toArray | Core 3.1 | 0.4801ns | 0.0074ns | 0.0069ns | 0.99 | 0.02 |
Scenario3 toArray | .NET 5 | 0.4854ns | 0.0108ns | 0.0101ns | 1.00 | 0.00 |
Scenario4 toList | Core 3.1 | 0.2452ns | 0.0024ns | 0.0022ns | 1.14 | 0.03 |
Scenario4 toList | .NET 5 | 0.2164ns | 0.0058ns | 0.0045ns | 1.00 | 0.00 |
Scenario4 toArray | Core 3.1 | 0.4812ns | 0.0082ns | 0.0064ns | 0.99 | 0.03 |
Scenario4 toArray | .NET 5 | 0.4856ns | 0.0119ns | 0.0111ns | 1.00 | 0.00 |
Scenario5 toList | Core 3.1 | 0.2381ns | 0.0060ns | 0.0050ns | 1.06 | 0.06 |
Scenario5 toList | .NET 5 | 0.2255ns | 0.0166ns | 0.0129ns | 1.00 | 0.00 |
Scenario5 toArray | Core 3.1 | 0.6015ns | 0.0365ns | 0.0391ns | 1.26 | 0.10 |
Scenario5 toArray | .NET 5 | 0.4802ns | 0.0115ns | 0.0107ns | 1.00 | 0.00 |
Hints
Outliers
Scenarios.Scenario1: .NET Core 3.1 -> 1 outlier was removed (29.51 ns)
Scenarios.Scenario2: .NET Core 3.1 -> 3 outliers were removed (8.72 ns..8.88 ns)
Scenarios.Scenario2: .NET Core 5.0 -> 2 outliers were removed (12.83 ns, 13.51 ns)
Scenarios.Scenario3_toList: .NET Core 5.0 -> 1 outlier was removed (2.01 ns)
Scenarios.Scenario4_toList: .NET Core 5.0 -> 3 outliers were removed (1.65 ns..1.67 ns)
Scenarios.Scenario4_toArray: .NET Core 3.1 -> 3 outliers were removed (1.87 ns..1.93 ns)
Scenarios.Scenario5_toList: .NET Core 3.1 -> 2 outliers were removed (1.64 ns, 1.65 ns)
Scenarios.Scenario5_toList: .NET Core 5.0 -> 3 outliers were removed (1.65 ns..1.68 ns)
Scenarios.Scenario5_toArray: .NET Core 3.1 -> 1 outlier was removed (2.08 ns)
Legends
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Ratio : Mean of the ratio distribution ([Current]/[Baseline])
RatioSD : Standard deviation of the ratio distribution ([Current]/[Baseline])
1 ns : 1 Nanosecond (0.000000001 sec)
Top comments (0)