-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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<TEnum?>.Default allocates #67842
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/area-system-collections Issue DetailsDescription
Here is a reproduction: using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ConsoleApp;
public static class Program
{
public static void Main()
{
_ = EqualityComparer<DayOfWeek?>.Default.Equals(DayOfWeek.Friday, DayOfWeek.Friday); // Warm-up
var before = GC.GetAllocatedBytesForCurrentThread();
_ = EqualityComparer<DayOfWeek?>.Default.Equals(DayOfWeek.Friday, DayOfWeek.Friday);
var after = GC.GetAllocatedBytesForCurrentThread();
Console.WriteLine(RuntimeInformation.FrameworkDescription);
Console.WriteLine(after > before ? "Allocates" : "Allocation-free");
}
} This results in:
If you replace ConfigurationI reproduced this on .NET 6 and on .NET 7 preview 2 on Windows x64, but this should be independent of the OS and architecture. Regression?This is not a regression. It also reproduces on .NET Framework 4.8. AnalysisThis is roughly due to the fact that I'm willing to provide a PR to fix this if you'd like.
|
I'll take a look, the problem that runtime/src/coreclr/vm/jitinterface.cpp Lines 8822 to 8827 in 7bfc61b
so we might want to introduce a |
Tagging subscribers to this area: @JulieLeeMSFT Issue DetailsDescription
Here is a reproduction: using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ConsoleApp;
public static class Program
{
public static void Main()
{
_ = EqualityComparer<DayOfWeek?>.Default.Equals(DayOfWeek.Friday, DayOfWeek.Friday); // Warm-up
var before = GC.GetAllocatedBytesForCurrentThread();
_ = EqualityComparer<DayOfWeek?>.Default.Equals(DayOfWeek.Friday, DayOfWeek.Friday);
var after = GC.GetAllocatedBytesForCurrentThread();
Console.WriteLine(RuntimeInformation.FrameworkDescription);
Console.WriteLine(after > before ? "Allocates" : "Allocation-free");
}
} This results in:
If you replace ConfigurationI reproduced this on .NET 6 and on .NET 7 preview 2 on Windows x64, but this should be independent of the OS and architecture. Regression?This is not a regression. It also reproduces on .NET Framework 4.8. AnalysisThis is roughly due to the fact that I'm willing to provide a PR to fix this if you'd like.
|
Thanks @EgorBo! 🙂 |
Description
EqualityComparer<TEnum?>.Default
(whenT
is a nullable enum) is resolved toObjectEqualityComparer<TEnum?>
, which boxes the enum when performing equality comparison. This causes an unnecessary allocation.Here is a reproduction:
This results in:
If you replace
DayOfWeek?
withDayOfWeek
, or if you use a type such asint?
instead, the code will printAllocation-free
.Configuration
I reproduced this on .NET 6 and on .NET 7 preview 2 on Windows x64, but this should be independent of the OS and architecture.
Regression?
This is not a regression. It also reproduces on .NET Framework 4.8.
Analysis
This is roughly due to the fact that
ComparerHelpers.CreateDefaultEqualityComparer
special-cases bothNullable<T>
and enums, but does not special-case nullable enums. This code path ends up usingObjectEqualityComparer<T>
.I'm willing to provide a PR to fix this if you'd like.
The text was updated successfully, but these errors were encountered: