-
Notifications
You must be signed in to change notification settings - Fork 789
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
[WIP] Devirtualize Equality #6175
Conversation
…izations. Thank you Don.
d8e2f38
to
34a3e84
Compare
The biggest thing holding me back on this is the discussion with the C# fellows (my fault, not theirs :) ). I also need to speak with @terrajobst of any types in the future that could implement |
@TIHan this PR would be really useful for performance-sensitive code we're writing atm. Is it possible to move forward without consensus with C#, in a way that won't bite us in the future? I'm specifically referring to the part of the PR which "optimizes current equality semantics to be devirtualized to IEquatable<'T>.Equals('T) for F# types" |
@saul , I talked with @terrajobst a bit. I'm not as concerned anymore; I just need to think through it. I want to make this right. This can be a priority for me as I want to get this in for 16.2. |
A concern I have is |
But that's already the case right? So this change only improves things - there are no drawbacks from what I can see. |
There would be no drawbacks to going ahead and using the rules that are not driven by the flag, |
This is great! Regarding IStructuralEquatable, presumably a generic version would help? dotnet/runtime#37482 |
This is very much out of date and represents an experiment that I don't think we'll be pursuing within the F# 5 timeframe. I'll close this out for now, but it is absolutely something we wish to address fully. |
This PR optimizes current equality semantics to be devirtualized to
IEquatable<'T>.Equals('T)
for F# types; this is to avoid boxing for struct types. It also adds--optimize:equality
for a even more optimistic approach to devirtualize equality toIEquatable<'T>.Equals('T)
for F#/.NET types that are custom equality and don't implementIStructuralEquatable
.This will solve most of the performance problems related to boxing when doing equality on struct types.
However, it is still possible that boxing on equality can occur if the F# type has the
[<CustomEquality>]
attribute and implementsIStructuralEquatable
;IStructuralEquatable.Equals(obj, IEqualityComparer)
will take priority overObject.Equals(obj)/IEquatable<'T>.Equals('T))
in this case, which means boxing for struct types. The same goes for .NET types. Meaning if a .NET type implementsIStructuralEquatable
, it will callIStructuralEquatable.Equals(obj, IEqualityComparer)
overObject.Equals(obj)/IEquatable<'T>.Equals('T))
.Remaining work:
hash
to devirtualize toGetHashCode
if it makes sense.C# may have a future feature with records and it's worth having just a bit of a conversation regarding equality semantics. My fear is that if C# gets struct records, we would still box on doing equality on them.
Also, I want to explore if we could just add a switch to always force
Object.Equals(obj)/IEquatable<'T>.Equals('T)
no matter if a type implementsIStructuralEquatable
or not. This way we can always guarantee a non-boxing call for equality, even if it changes semantics. I don't want to rule this out just yet; probably won't happen, but it would be good to note it down here.