Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize generic collection Equal #840

Merged
merged 1 commit into from
Apr 29, 2018

Conversation

jnyrup
Copy link
Member

@jnyrup jnyrup commented Apr 28, 2018

This PR optimizes Equal for generic collections as #490 mentioned performance problems.
The slowdown was mostly due generic collections of value types being boxed.

A minor downside is that now the subject will now be enumerated twice when failing, whereas before it was a copy of the subject that got enumerated in EnumerableValueFormatter.
I believe this is worthwhile as we should optimize for tests passing.

In the benchmark:

  • CollectionEqual_NonGeneric is equivalent to the current behavior,
  • CollectionEqual_Generic is the optimized version from this PR.
  • CollectionEqual_Generic_Equality is using a custom comparer in the benchmark, (int s, int e) => s == e in this example.
BenchmarkDotNet=v0.10.14, OS=Windows 10.0.16299.371 (1709/FallCreatorsUpdate/Redstone3)
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
Frequency=2531245 Hz, Resolution=395.0625 ns, Timer=TSC
  [Host]    : .NET Framework 4.7.1 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2633.0
  RyuJitX86 : .NET Framework 4.7.1 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.2633.0

Job=RyuJitX86  Jit=RyuJit  Platform=X86

                                  Method |     N |         Mean |      Error |     StdDev | Scaled |    Gen 0 |   Gen 1 | Allocated |
---------------------------------------- |------ |-------------:|-----------:|-----------:|-------:|---------:|--------:|----------:|
              CollectionEqual_NonGeneric |    10 |     4.623 us |  0.0534 us |  0.0500 us |   1.00 |   0.6866 |       - |   2.12 KB |
                 CollectionEqual_Generic |    10 |     1.563 us |  0.0224 us |  0.0210 us |   0.34 |   0.5054 |       - |   1.56 KB |
 CollectionEqual_Generic_IsSameOrEqualTo |    10 |     1.586 us |  0.0174 us |  0.0162 us |   0.34 |   0.5436 |       - |   1.68 KB |
        CollectionEqual_Generic_Equality |    10 |     1.476 us |  0.0123 us |  0.0115 us |   0.32 |   0.4673 |       - |   1.44 KB |
                                         |       |              |            |            |        |          |         |           |
              CollectionEqual_NonGeneric |   100 |    26.771 us |  0.2284 us |  0.2137 us |   1.00 |   1.9531 |       - |   6.05 KB |
                 CollectionEqual_Generic |   100 |     2.945 us |  0.0351 us |  0.0328 us |   0.11 |   0.8469 |       - |   2.61 KB |
 CollectionEqual_Generic_IsSameOrEqualTo |   100 |     3.751 us |  0.0633 us |  0.0561 us |   0.14 |   1.2283 |       - |   3.79 KB |
        CollectionEqual_Generic_Equality |   100 |     2.501 us |  0.0391 us |  0.0366 us |   0.09 |   0.4654 |       - |   1.44 KB |
                                         |       |              |            |            |        |          |         |           |
              CollectionEqual_NonGeneric |  1000 |   242.738 us |  3.3402 us |  3.1244 us |   1.00 |  13.1836 |       - |  41.22 KB |
                 CollectionEqual_Generic |  1000 |    16.479 us |  0.2279 us |  0.2132 us |   0.07 |   4.2725 |       - |  13.16 KB |
 CollectionEqual_Generic_IsSameOrEqualTo |  1000 |    24.522 us |  0.2887 us |  0.2701 us |   0.10 |   8.0872 |       - |  24.88 KB |
        CollectionEqual_Generic_Equality |  1000 |    12.737 us |  0.1292 us |  0.1209 us |   0.05 |   0.4578 |       - |   1.44 KB |
                                         |       |              |            |            |        |          |         |           |
              CollectionEqual_NonGeneric |  5000 | 1,247.512 us | 14.8358 us | 13.1515 us |   1.00 |  74.2188 |  9.7656 | 247.05 KB |
                 CollectionEqual_Generic |  5000 |    76.284 us |  1.1535 us |  1.0790 us |   0.06 |  19.5313 |       - |  60.04 KB |
 CollectionEqual_Generic_IsSameOrEqualTo |  5000 |   116.489 us |  0.8728 us |  0.7737 us |   0.09 |  38.5742 |       - | 118.63 KB |
        CollectionEqual_Generic_Equality |  5000 |    57.726 us |  0.4890 us |  0.4574 us |   0.05 |   0.4272 |       - |   1.44 KB |
                                         |       |              |            |            |        |          |         |           |
              CollectionEqual_NonGeneric | 10000 | 2,511.052 us | 27.8286 us | 26.0309 us |   1.00 | 113.2813 | 39.0625 | 492.26 KB |
                 CollectionEqual_Generic | 10000 |   150.334 us |  2.0317 us |  1.9005 us |   0.06 |  38.5742 |       - | 118.63 KB |
 CollectionEqual_Generic_IsSameOrEqualTo | 10000 |   231.409 us |  1.7973 us |  1.6812 us |   0.09 |  76.6602 |       - | 235.82 KB |
        CollectionEqual_Generic_Equality | 10000 |   114.122 us |  1.0269 us |  0.8575 us |   0.05 |   0.3662 |       - |   1.44 KB |

@jnyrup jnyrup merged commit 36c0d6c into fluentassertions:master Apr 29, 2018
@jnyrup jnyrup deleted the EqualOptimizations branch April 29, 2018 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants