Skip to content

Instantly share code, notes, and snippets.

@xoofx
Created February 19, 2019 19:56
Show Gist options
  • Save xoofx/84126db63ef48a6eee4ac5811c1a932f to your computer and use it in GitHub Desktop.
Save xoofx/84126db63ef48a6eee4ac5811c1a932f to your computer and use it in GitHub Desktop.
Benchmarks of calli vs delegate
// | Method | Mean | Error | StdDev |
// |------------- |----------:|----------:|----------:|
// | Calli | 0.6718 ns | 0.0013 ns | 0.0012 ns |
// | Delegate | 1.1366 ns | 0.0099 ns | 0.0088 ns |
// | FastDelegate | 1.6239 ns | 0.0103 ns | 0.0097 ns |
// MyClassLib.cs is compiled in another project (havent tested if compiling with Fody is working with BenchmarkDotnet in the same project)
// This file is referencing BenchDelegates.MyClassLib
using System;
using System.Linq.Expressions;
using BenchDelegates;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using FastExpressionCompiler;
namespace BenchDelegatesApp
{
public class Program
{
private readonly MyClass _instance = new MyClass();
private readonly IntPtr _funcPtr;
private readonly Action<object, int> _delegate;
private readonly Action<object, int> _fastDelegate;
public Program()
{
_funcPtr = MyClassLib.GetMyClassIncrementValueFunctionPointer();
_delegate = (obj, inc) => ((MyClass)obj).IncrementValue(inc);
Expression<Action<object, int>> expr = (obj, inc) => ((MyClass)obj).IncrementValue(inc);
_fastDelegate = expr.CompileFast();
}
[Benchmark]
public void Calli()
{
MyClassLib.CallIndirect(_instance, _funcPtr, 1);
}
[Benchmark]
public void Delegate()
{
_delegate(_instance, 1);
}
[Benchmark]
public void FastDelegate()
{
_fastDelegate(_instance, 1);
}
static void Main(string[] args)
{
BenchmarkRunner.Run<Program>();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<InlineIL />
</Weavers>
// This file is compiled using https://github.com/ltrzesniewski/InlineIL.Fody
// with the associated FodyWeavers.xml
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using InlineIL;
using static InlineIL.IL.Emit;
namespace BenchDelegates
{
public class MyClass
{
private int _value;
public int Value => _value;
public void IncrementValue(int inc)
{
_value += inc;
}
}
public class MyClassLib
{
public static IntPtr GetMyClassIncrementValueFunctionPointer()
{
Ldftn(new MethodRef(typeof(MyClass), nameof(MyClass.IncrementValue), new TypeRef(typeof(int))));
return IL.Return<IntPtr>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CallIndirect(object instance, IntPtr functionPtr, int inc)
{
IL.Push(instance);
IL.Push(inc);
IL.Push(functionPtr);
Calli(new StandAloneMethodSig(CallingConventions.Standard | CallingConventions.HasThis, typeof(void), typeof(int)));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment