public class Benchmark2
{
private Base1 _b1;
private Base2 _b2;
[GlobalSetup]
public void Setup()
{
_b1 = new Sub1();
_b2 = new Sub2();
}
[Benchmark(Baseline = true)]
public int M1()
{
int r = 0;
for (int i = 0; i < 1000; i++)
{
r += _b1.Method(i);
}
return r;
}
[Benchmark]
public int M2()
{
int r = 0;
for (int i = 0; i < 1000; i++)
{
r += _b2.Method(i);
}
return r;
}
}
public abstract class Base1
{
public abstract int Method(int a);
}
public sealed class Sub1 : Base1
{
private int _a;
public override int Method(int a) => a - _a;
}
public abstract unsafe class Base2
{
private readonly delegate*<Base2, int, int> _methodPtr;
protected Base2(delegate*<Base2, int, int> methodPtr) => _methodPtr = methodPtr;
public int Method(int a) => _methodPtr(this, a);
}
public sealed unsafe class Sub2 : Base2
{
private int _a;
public Sub2() : base(&Method) { }
private static int Method(Base2 inst, int a) => a - Unsafe.As<Base2, Sub2>(ref inst)._a;
}
; Method CodingLab.ParseIt.Console.Benchmark2:M1():int:this (FullOpts)
G_M000_IG01: ;; offset=0000H
push rdi
push rsi
push rbx
sub rsp, 32
mov rbx, rcx
G_M000_IG02: ;; offset=000AH
xor esi, esi
xor edi, edi
G_M000_IG03: ;; offset=000EH
mov rcx, gword ptr [rbx+08H]
mov edx, edi
mov rax, qword ptr [rcx]
mov rax, qword ptr [rax+40H]
call [rax+20H]CodingLab.ParseIt.Console.Base1:Method(int):int:this ; See Sub1::Method codegen below
add esi, eax
inc edi
cmp edi, 0x3E8
jl SHORT G_M000_IG03
G_M000_IG04: ;; offset=002AH
mov eax, esi
G_M000_IG05: ;; offset=002CH
add rsp, 32
pop rbx
pop rsi
pop rdi
ret
; END METHOD CodingLab.ParseIt.Console.Benchmark2:M1():int:this
; Total bytes of code: 52
; public sealed class Sub1 : Base1
; {
; private int _a;
;
; [MethodImpl(MethodImplOptions.AggressiveInlining)]
; public override int Method(int a)
; {
; return a - _a;
mov eax,edx
sub eax,dword ptr [rcx+8]
ret
; Method CodingLab.ParseIt.Console.Benchmark2:M2():int:this (FullOpts)
G_M000_IG01: ;; offset=0000H
push rdi
push rsi
push rbx
sub rsp, 32
mov rbx, rcx
G_M000_IG02: ;; offset=000AH
xor esi, esi
xor edi, edi
G_M000_IG03: ;; offset=000EH
mov rcx, gword ptr [rbx+10H]
mov rax, qword ptr [rcx+08H]
mov edx, edi
call rax ; See Sub2::Method codegen below
add esi, eax
inc edi
cmp edi, 0x3E8
jl SHORT G_M000_IG03
G_M000_IG04: ;; offset=0026H
mov eax, esi
G_M000_IG05: ;; offset=0028H
add rsp, 32
pop rbx
pop rsi
pop rdi
ret
; END METHOD CodingLab.ParseIt.Console.Benchmark2:M2():int:this
; Total bytes of code: 48
; public sealed unsafe class Sub2 : Base2
; {
; private int _a;
;
; public Sub2() : base(&Method) {}
;
; [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
; private static int Method(Base2 inst, int a)
; {
; return a - Unsafe.As<Base2, Sub2>(ref inst)._a;
mov eax,edx
sub eax,dword ptr [rcx+10h]
ret
| Method | Mean | StdDev | Ratio | Code Size | Allocated | Alloc Ratio |
|------- |-----------:|--------:|------:|----------:|----------:|------------:|
| M1 | 460.5 ns | 1.10 ns | 1.00 | 86 B | - | NA |
| M2 | 1,605.9 ns | 3.81 ns | 3.49 | 48 B | - | NA |