Benchmark: Check to Skip
Tags: benchmark, dotnet, performance, codequality
Published: 2021-02-10 18:23:29

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:

{% github AntonioFalcao/Benchmark no-readme %}

## Scenarios

```c#
// 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

``` ini

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

```ini
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

```ini
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)
```