-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
EqualityComparer<T>.Default.Equals doesn't devirtualize in a shared generic #10050
Comments
I don't believe the jit can devirtualize in this case in general. For ref type In the typical case where the caller of If As noted in dotnet/corefx#28511 if you are doing a lot of comparisons using the default comparer the performant patterns for value and ref types differ. This is unfortunate. For ref types caching the result of We should investigate what it would take to fix the jit so the same patterns perform equally well for value and ref types. |
Hmm... that makes it more complicated and means I can't do a simple fallback to |
I think best can do is going back to caching in a local for object types 😢 Will treat it as a resolution to the regression rather than something more general |
As aside (future) could generic lookups in loops be hoisted outside of loops? |
Yes, that is part of getting the jit changes correct. I'd like to make it so that if you call The second part of the fix is that if you cache the jit needs to be more flexible in propagating the devirtualized comparer to the use site. This is a bit trickier to arrange since devirtualization happens so early, but I think we can make it work provided the caching is done "near" the use. That way if you cache to get good perf for ref types (or have legacy code that cached because prior to all this devirtualization, caching was a win for both ref and value types) you now get the benefits of devirtualization. |
Looked into this a bit, here are some notes: To enable hoisting
|
- [X] Adds the ability to store a null value in an ordered hash set TODO: Optimized the OrderedHashSet. See this: * dotnet/runtime#10050 Looks like the OrderedDictionary that I based this structure from was not updated. See the source for diffing: https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs Difference between a HashSet and an OrderedHashSet is updating the indexes of the entries after fixing the chain to preserve insertion order.
…#679) * Optimizes OrderedHashSet using the learnings here: dotnet/runtime#10050 * Removes ValueCollection since it was a relic from the conversion of the OrderedDictionary * Centralizes throw strings. * Adds pooled ordered hash set (but doesn't use it) Closes #448
@EgorBo can you post updated perf for your benchmark(s) above? |
I don't think anything has changed for it, we bail out on devirtualizing it (and PGO refuses to devirt it either due to lookup-via-this/indirect call, something like that), but let me kick off a run via bot.. |
@EgorBot -intel -arm64 using System;
using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Running;
public class StringComparisons
{
private string s1 = "1";
private string s2 = "1";
[Benchmark]
public bool Equals_inline() => string.Equals(s1, s2);
[Benchmark]
public bool Equals_specialized() => EqualityComparer<string>.Default.Equals(s1, s2);
[Benchmark]
public bool Equals_generic() => GenericEquals(s1, s2);
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool GenericEquals<T>(T a, T b) => EqualityComparer<T>.Default.Equals(a, b);
} |
cc @AndyAyersMS results in EgorBot/runtime-utils#120 probably better now? hard to say |
It potentially could since it resolves to calls on
object
.However more pressing is regression in dictionary for object types https://github.com/dotnet/corefx/issues/28511
/cc @AndyAyersMS @danmosemsft @ianhays
category:cq
theme:devirtualization
skill-level:intermediate
cost:medium
impact:medium
The text was updated successfully, but these errors were encountered: