-
Notifications
You must be signed in to change notification settings - Fork 275
/
Copy pathDefaultEqualityComparerPerf.cs
84 lines (69 loc) · 2.76 KB
/
DefaultEqualityComparerPerf.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using MicroBenchmarks;
// Performance tests for optimizations related to EqualityComparer<T>.Default
namespace Devirtualization
{
public class EqualityComparerFixture<T> where T : IEquatable<T>
{
IEqualityComparer<T> comparer;
public EqualityComparerFixture(IEqualityComparer<T> customComparer = null)
{
comparer = customComparer ?? EqualityComparer<T>.Default;
}
// Baseline method showing unoptimized performance
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public bool CompareNoOpt(ref T a, ref T b)
{
return EqualityComparer<T>.Default.Equals(a, b);
}
// The code this method invokes should be well-optimized
[MethodImpl(MethodImplOptions.NoInlining)]
public bool Compare(ref T a, ref T b)
{
return EqualityComparer<T>.Default.Equals(a, b);
}
// This models how Dictionary uses a comparer. We're not
// yet able to optimize such cases.
[MethodImpl(MethodImplOptions.NoInlining)]
public bool CompareCached(ref T a, ref T b)
{
return comparer.Equals(a, b);
}
private static IEqualityComparer<T> Wrapped()
{
return EqualityComparer<T>.Default;
}
// We would need enhancements to late devirtualization
// to optimize this case.
[MethodImpl(MethodImplOptions.NoInlining)]
public bool CompareWrapped(ref T x, ref T y)
{
return Wrapped().Equals(x, y);
}
}
[BenchmarkCategory(Categories.Runtime, Categories.Virtual)]
public class EqualityComparer
{
public enum E
{
RED = 1,
BLUE = 2
}
private EqualityComparerFixture<ValueTuple<byte, E, int>> valueTupleFixture = new EqualityComparerFixture<ValueTuple<byte, E, int>>();
private ValueTuple<byte, E, int> v0 = new ValueTuple<byte, E, int>(3, E.RED, 11);
[Benchmark]
public bool ValueTupleCompareNoOpt() => valueTupleFixture.CompareNoOpt(ref v0, ref v0);
[Benchmark]
public bool ValueTupleCompare() => valueTupleFixture.Compare(ref v0, ref v0);
[Benchmark]
public bool ValueTupleCompareCached() => valueTupleFixture.CompareCached(ref v0, ref v0);
[Benchmark]
public bool ValueTupleCompareWrapped() => valueTupleFixture.CompareWrapped(ref v0, ref v0);
}
}