-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Generic type check allocates for nullable structs #95685
Comments
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsDescriptionThe following two methods ( public static bool M1<T>(T value) => value is S;
public static bool M2<T>(T value)
{
if (typeof(T) == typeof(S))
{
return true;
}
else if (typeof(T) == typeof(S?))
{
return Unsafe.As<T, S?>(ref value).HasValue;
}
return false;
} However, to my surprise, When To confirm, I profiled the following code: long x = 0;
S? value = new S();
for (long i = 0; i < long.MaxValue - 1; i++)
{
x += M1(value) ? 0 : 1;
}
Console.WriteLine(x); I used Visual Studio with .NET Object Allocation Tracking, and it confirmed that These observations also hold for a slightly different version (from which I came) but I suppose it has the same underlying issue: interface I { }
struct S : I { }
static bool M1<T>(T value) => value is I; I believe this simple code definitely should not allocate. ConfigurationWindows 10, .NET 7 and .NET 8.
|
Basically, |
Thanks for reporting! Fixed in .NET 9.0 |
Description
The following two methods (
M1
,M2
) should behave identically:However, to my surprise,
M1
seems to allocate whenT
is a nullable struct.Here's SharpLab's link: https://sharplab.io/#v2:EYLgtghglgdgNAFxBAzmAPgAQEwEYCwAUJgAwAEAygBYQBOADgDITAB0ASgK4wJRgCmAbiKkymXB268BrAMIB7MPSgAbfrQrqAblADG/FMMJEUCWp10JKZAN4BfEdjKyyRG0TKeyAbQBSUBABxfhh1PQAKBABPen55ADNwigBKZIBdDy8/AODQ2gjo2ITw2ARUjMIvH38gkLDdSJi4xIoAfnLMz2zavIKm4tL29M6xAGYxXAA2MmB5eRUyAFlcAB4AFQA+cLWyLQgVTn5ksgBeDd39w7IoFEojEe7c+sailo7KrJqn/IbC5pKeO8qo86j8Xv82kDPjlQX1XgCEEMKlVMONxNNZvMlth1lsdnsDkcRu4PlVPFB4mRwcU1scTicyH9iilkiMqiSyZyxAB2RnmIRsrwOUlk/gqFD8a6U6mJWmnBlMlpDQWeDlclG8gCqMBQEHi/FYAEEUOs4JRWltaPxKQTDslWAAJVAANUuApFVWF6swvPi+wlRk9RDsQA
When
T
is a non-nullable struct, the JIT is smart enough to know the result beforehand.When
T
is a nullable struct the resulting code callsSystem.Runtime.CompilerServices.RuntimeHelpers.Box(System.Runtime.CompilerServices.MethodTable*, Byte ByRef)
.To confirm, I profiled the following code:
I used Visual Studio with .NET Object Allocation Tracking, and it confirmed that
M1
allocates whileM2
does not.These observations also hold for a slightly different version (from which I came) but I suppose it has the same underlying issue:
I believe this simple code definitely should not allocate.
Configuration
Windows 10, .NET 7 and .NET 8.
The text was updated successfully, but these errors were encountered: