-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Open
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone
Description
Repro:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Runtime.CompilerServices;
[MemoryDiagnoser]
[DisassemblyDiagnoser]
public class Program
{
static void Main(string[] args) => BenchmarkSwitcher.FromAssemblies(new[] { typeof(Program).Assembly }).Run(args);
private S _s = default(S);
private C _c = new C();
private S? _ns = (S?)default(S);
[Benchmark] public int Struct() => CallM(_s);
[Benchmark] public int Class() => CallM(_c);
[Benchmark] public int Nullable() => CallM(_ns);
[Benchmark] public int NullableSpecialized() => CallMSpecial(_ns);
static int CallM<T>(T t)
{
if (t is IMyInterface)
{
return ((IMyInterface)t).M();
}
return 0;
}
static int CallMSpecial<T>(T? t) where T : struct
{
if (t.HasValue)
{
return CallM(t.GetValueOrDefault());
}
return 0;
}
}
interface IMyInterface
{
int M();
}
struct S : IMyInterface
{
public int M() => 42;
}
class C : IMyInterface
{
public int M() => 42;
}| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | Code Size |
|---|---|---|---|---|---|---|---|---|
| Struct | 0.4807 ns | 0.0044 ns | 0.0037 ns | - | - | - | - | 16 B |
| Class | 3.0842 ns | 0.0045 ns | 0.0038 ns | - | - | - | - | 86 B |
| Nullable | 88.6692 ns | 0.5664 ns | 0.4729 ns | 0.0076 | - | - | 48 B | 132 B |
| NullableSpecialized | 1.5149 ns | 0.0087 ns | 0.0077 ns | - | - | - | - | 64 B |
Is there anything we can do to make the nullable case faster and less inclined to box without needing a special code path to handle it (e.g. my CallMSpecial, which in my current actual code is another overload so that a nullable binds to it more tightly).
Here's what the codegen for the nullable case looks like:
; Program.CallM[[System.Nullable`1[[S, Benchmarks]], System.Private.CoreLib]](System.Nullable`1<S>)
sub rsp,28
mov [rsp+30],rcx
lea rdx,[rsp+30]
mov rcx,offset MT_System.Nullable`1[[S, Benchmarks]]
call CORINFO_HELP_BOX_NULLABLE
mov rdx,rax
mov rcx,offset MT_IMyInterface
call CORINFO_HELP_ISINSTANCEOFINTERFACE
test rax,rax
je short M01_L00
lea rdx,[rsp+30]
mov rcx,offset MT_System.Nullable`1[[S, Benchmarks]]
call CORINFO_HELP_BOX_NULLABLE
mov rdx,rax
mov rcx,offset MT_IMyInterface
call CORINFO_HELP_CHKCASTINTERFACE
mov rcx,rax
mov r11,7FFCDCEE05D0
call qword ptr [7FFCDD2705D0]
nop
add rsp,28
ret
M01_L00:
xor eax,eax
add rsp,28
ret
; Total bytes of code 122category:cq
theme:basic-cq
skill-level:intermediate
cost:medium
impact:small
pentp, PaulusParssinen, NN---, austindrenski, avsorokin and 2 more
Metadata
Metadata
Assignees
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Type
Projects
Status
Optimizations