-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
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
Ran from a VM due to dotnet/BenchmarkDotNet#1499
BenchmarkDotNet=v0.12.1, OS=Windows 10.0.17763.1039 (1809/October2018Update/Redstone5)
Intel Core i7-4980HQ CPU 2.80GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=5.0.100-preview.6.20318.15
[Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.30506, CoreFX 5.0.20.30506), X64 RyuJIT
ShortRun : .NET Core 5.0.0 (CoreCLR 5.0.20.30506, CoreFX 5.0.20.30506), X64 RyuJIT
Job=ShortRun IterationCount=3 LaunchCount=1
WarmupCount=3
Method | Mean | Error | StdDev | Code Size |
---|---|---|---|---|
Combined | 3.6617 ns | 0.9868 ns | 0.0541 ns | 42 B |
Separate | 3.6139 ns | 0.4095 ns | 0.0224 ns | 42 B |
JustMe | 0.0000 ns | 0.0000 ns | 0.0000 ns | 6 B |
The idea is to do a two step virtual call, once dispatching from this
(Combined) and once to a separate sealed class (Separate), JustMe is the control as it devirtualizes correctly.
using System;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
namespace test2
{
public interface IMe
{
bool Hello();
}
public interface IYou
{
IMe You { get; }
}
public sealed class Combined : IMe, IYou
{
public IMe You => this;
public bool Hello() => true;
}
public sealed class MeImpl : IMe
{
public bool Hello() => true;
}
public sealed class YouImpl : IYou
{
public IMe You => new MeImpl();
}
[ShortRunJob, DisassemblyDiagnoser(exportGithubMarkdown: true)]
public class Program
{
[Benchmark]
public bool Combined() => new Combined().You.Hello();
[Benchmark]
public bool Separate() => new YouImpl().You.Hello();
[Benchmark]
public bool JustMe() => new MeImpl().Hello();
static void Main(string[] args)
{
BenchmarkRunner.Run<Program>();
}
}
}
And the resulting asm:
.NET Core 5.0.0 (CoreCLR 5.0.20.30506, CoreFX 5.0.20.30506), X64 RyuJIT
; test2.Program.Combined()
sub rsp,28
mov rcx,offset MT_test2.Combined
call CORINFO_HELP_NEWSFAST
mov rcx,rax
mov rax,[7FFA0807B738]
add rsp,28
jmp rax
; Total bytes of code 36
; test2.Combined.Hello()
mov eax,1
ret
; Total bytes of code 6
.NET Core 5.0.0 (CoreCLR 5.0.20.30506, CoreFX 5.0.20.30506), X64 RyuJIT
; test2.Program.Separate()
sub rsp,28
mov rcx,offset MT_test2.MeImpl
call CORINFO_HELP_NEWSFAST
mov rcx,rax
mov rax,[7FFA0808B7F0]
add rsp,28
jmp rax
; Total bytes of code 36
; test2.MeImpl.Hello()
mov eax,1
ret
; Total bytes of code 6
.NET Core 5.0.0 (CoreCLR 5.0.20.30506, CoreFX 5.0.20.30506), X64 RyuJIT
; test2.Program.JustMe()
mov eax,1
ret
; Total bytes of code 6
Expectation would be that all benchmarks compile down to mov eax, 1
category:cq
theme:devirtualization
skill-level:expert
cost:large
impact:medium
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