Skip to content

Instantly share code, notes, and snippets.

@ig-sinicyn
Last active December 15, 2016 11:21
Show Gist options
  • Save ig-sinicyn/4e1be90a708695a02e02ca85e823d4f2 to your computer and use it in GitHub Desktop.
Save ig-sinicyn/4e1be90a708695a02e02ca85e823d4f2 to your computer and use it in GitHub Desktop.

Baseline - GetViaProperty

                        Method |          Mean |    StdDev |   Scaled | Scaled-StdDev |  Gen 0 | Allocated |
------------------------------ |-------------- |---------- |--------- |-------------- |------- |---------- |
        GetViaPropertyNoInline |     1.9537 ns | 0.0379 ns |     3.63 |          0.10 |      - |       0 B |
                GetViaProperty |     0.5387 ns | 0.0117 ns |     1.00 |          0.00 |      - |       0 B |
                GetViaDelegate |     4.9861 ns | 0.1827 ns |     9.26 |          0.38 |      - |       0 B |
                  GetViaILEmit |     5.0013 ns | 0.1399 ns |     9.29 |          0.32 |      - |       0 B |
 GetViaCompiledExpressionTrees |    14.3807 ns | 0.1524 ns |    26.71 |          0.62 |      - |       0 B |
              GetViaFastMember |    42.7589 ns | 0.2952 ns |    79.41 |          1.74 |      - |       0 B |
   GetViaReflectionWithCaching |   137.3350 ns | 0.3372 ns |   255.05 |          5.34 |      - |       0 B |
              GetViaReflection |   213.7216 ns | 1.2898 ns |   396.90 |          8.58 |      - |       0 B |
   GetViaDelegateDynamicInvoke | 1,002.3362 ns | 6.0643 ns | 1,861.45 |         40.25 | 0.0201 |     208 B |
       SetViaPropertytNoInline |     3.1143 ns | 0.0227 ns |     5.78 |          0.13 |      - |       0 B |
                SetViaProperty |     2.3626 ns | 0.0073 ns |     4.39 |          0.09 |      - |       0 B |
                SetViaDelegate |    10.9459 ns | 0.0500 ns |    20.33 |          0.43 |      - |       0 B |
                  SetViaILEmit |    11.5839 ns | 0.0509 ns |    21.51 |          0.46 |      - |       0 B |
 SetViaCompiledExpressionTrees |    12.3012 ns | 0.0483 ns |    22.84 |          0.48 |      - |       0 B |
              SetViaFastMember |    43.6908 ns | 0.2723 ns |    81.14 |          1.76 |      - |       0 B |
   SetViaReflectionWithCaching |   238.2641 ns | 1.2897 ns |   442.48 |          9.50 | 0.0083 |      64 B |
              SetViaReflection |   315.8556 ns | 2.4288 ns |   586.58 |         12.96 | 0.0081 |      64 B |
   SetViaDelegateDynamicInvoke | 1,070.0709 ns | 5.6260 ns | 1,987.24 |         42.59 | 0.0259 |     224 B |

Baseline - GetViaPropertyNoInline


                        Method |          Mean |    StdDev | Scaled | Scaled-StdDev |  Gen 0 | Allocated |
------------------------------ |-------------- |---------- |------- |-------------- |------- |---------- |
        GetViaPropertyNoInline |     1.9329 ns | 0.0182 ns |   1.00 |          0.00 |      - |       0 B |
                GetViaProperty |     0.5393 ns | 0.0189 ns |   0.28 |          0.01 |      - |       0 B |
                GetViaDelegate |     4.9466 ns | 0.1549 ns |   2.56 |          0.08 |      - |       0 B |
                  GetViaILEmit |     4.9713 ns | 0.1211 ns |   2.57 |          0.06 |      - |       0 B |
 GetViaCompiledExpressionTrees |    14.3409 ns | 0.1059 ns |   7.42 |          0.09 |      - |       0 B |
              GetViaFastMember |    42.4708 ns | 0.2297 ns |  21.97 |          0.23 |      - |       0 B |
   GetViaReflectionWithCaching |   137.0271 ns | 0.7545 ns |  70.90 |          0.74 |      - |       0 B |
              GetViaReflection |   213.7742 ns | 1.0812 ns | 110.61 |          1.14 |      - |       0 B |
   GetViaDelegateDynamicInvoke | 1,001.8111 ns | 2.7320 ns | 518.34 |          4.87 | 0.0191 |     208 B |
       SetViaPropertytNoInline |     3.1343 ns | 0.0333 ns |   1.62 |          0.02 |      - |       0 B |
                SetViaProperty |     2.0968 ns | 0.0255 ns |   1.08 |          0.02 |      - |       0 B |
                SetViaDelegate |    10.9902 ns | 0.0815 ns |   5.69 |          0.07 |      - |       0 B |
                  SetViaILEmit |    11.6530 ns | 0.0158 ns |   6.03 |          0.06 |      - |       0 B |
 SetViaCompiledExpressionTrees |    12.3282 ns | 0.0532 ns |   6.38 |          0.06 |      - |       0 B |
              SetViaFastMember |    43.1414 ns | 0.1237 ns |  22.32 |          0.21 |      - |       0 B |
   SetViaReflectionWithCaching |   237.0956 ns | 0.8838 ns | 122.67 |          1.19 | 0.0088 |      64 B |
              SetViaReflection |   315.5029 ns | 0.6867 ns | 163.24 |          1.51 | 0.0076 |      64 B |
   SetViaDelegateDynamicInvoke | 1,088.2038 ns | 6.8264 ns | 563.04 |          6.12 | 0.0259 |     224 B |
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
using FastMember;
using Sigil;
using Magnum.Reflection;
namespace ReflectionBenchmarks
{
[Config(typeof(Config))]
public class Program
{
private class Config : ManualConfig
{
public Config()
{
Add(new BenchmarkDotNet.Diagnosers.MemoryDiagnoser());
}
}
private static BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
private static string propertyName = "PublicHost";
private static TestUri testUri;
private static Object @object;
private static Type @class;
private static PropertyInfo property;
private static FastProperty fastProperty;
private static TypeAccessor accessor; // FastMember
private static Func<TestUri, string> getter;
private static Action<TestUri, string> setter;
public static Func<TestUri, string> getDelegate;
public static Action<TestUri, string> setDelegate;
public static Delegate getDelegateDynamic, setDelegateDynamic;
//private static bool allowNonPublicFieldAccess = false;
private static bool allowNonPublicFieldAccess = true;
static Program()
{
testUri = new TestUri("SomeHost");
@object = testUri;
@class = testUri.GetType();
property = @class.GetProperty(propertyName, bindingFlags);
fastProperty = new FastProperty(property);
// Using FastMember - https://github.com/mgravell/fast-member
accessor = TypeAccessor.Create(@class, allowNonPublicAccessors: allowNonPublicFieldAccess);
var funcType = Type.GetType("System.Func`2[ReflectionBenchmarks.Program+TestUri, System.String]");
getDelegate = (Func<TestUri, string>)Delegate.CreateDelegate(funcType, property.GetGetMethod(nonPublic: allowNonPublicFieldAccess));
getDelegateDynamic = Delegate.CreateDelegate(funcType, property.GetGetMethod(nonPublic: allowNonPublicFieldAccess));
var actionType = Type.GetType("System.Action`2[ReflectionBenchmarks.Program+TestUri, System.String]");
setDelegate = (Action<TestUri, string>)Delegate.CreateDelegate(actionType, property.GetSetMethod(nonPublic: allowNonPublicFieldAccess));
setDelegateDynamic = Delegate.CreateDelegate(actionType, property.GetSetMethod(nonPublic: allowNonPublicFieldAccess));
var setterEmiter = Emit<Action<TestUri, string>>
.NewDynamicMethod("SetTestUriProperty")
.LoadArgument(0)
.LoadArgument(1)
.Call(property.GetSetMethod(nonPublic: allowNonPublicFieldAccess))
.Return();
setter = setterEmiter.CreateDelegate();
var getterEmiter = Emit<Func<TestUri, string>>
.NewDynamicMethod("GetTestUriProperty")
.LoadArgument(0)
.Call(property.GetGetMethod(nonPublic: allowNonPublicFieldAccess))
.Return();
getter = getterEmiter.CreateDelegate();
}
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<Program>();
}
[Benchmark(Baseline = true)]
public string GetViaPropertyNoInline()
{
return testUri.PublicHostNoInline;
}
[Benchmark]
public string GetViaProperty()
{
return testUri.PublicHost;
}
[Benchmark]
public string GetViaDelegate()
{
return getDelegate(testUri);
}
[Benchmark]
public string GetViaILEmit()
{
return getter(testUri);
}
[Benchmark]
public string GetViaCompiledExpressionTrees()
{
return (string)fastProperty.Get(testUri);
}
[Benchmark]
public string GetViaFastMember()
{
return (string)accessor[testUri, "PublicHost"];
}
[Benchmark]
public string GetViaReflectionWithCaching()
{
return (string)property.GetValue(testUri, null);
}
[Benchmark]
public string GetViaReflection()
{
Type @class = testUri.GetType();
PropertyInfo property = @class.GetProperty(propertyName, bindingFlags);
return (string)property.GetValue(testUri, null);
}
[Benchmark]
public string GetViaDelegateDynamicInvoke()
{
return (string)getDelegateDynamic.DynamicInvoke(testUri);
}
[Benchmark]
public void SetViaPropertytNoInline()
{
testUri.PublicHostNoInline = "Testing";
}
[Benchmark]
public void SetViaProperty()
{
testUri.PublicHost = "Testing";
}
[Benchmark]
public void SetViaDelegate()
{
setDelegate(testUri, "Testing");
}
[Benchmark]
public void SetViaILEmit()
{
setter(testUri, "Testing");
}
[Benchmark]
public void SetViaCompiledExpressionTrees()
{
fastProperty.Set(testUri, "Testing");
}
[Benchmark]
public void SetViaFastMember()
{
accessor[testUri, "PublicHost"] = "Testing";
}
[Benchmark]
public void SetViaReflectionWithCaching()
{
property.SetValue(testUri, "Testing", null);
}
[Benchmark]
public void SetViaReflection()
{
Type @class = testUri.GetType();
PropertyInfo property = @class.GetProperty(propertyName, bindingFlags);
property.SetValue(testUri, "Testing", null);
}
[Benchmark]
public void SetViaDelegateDynamicInvoke()
{
setDelegateDynamic.DynamicInvoke(testUri, "Testing");
}
public class TestUri
{
public TestUri(Uri uri)
{
Host = uri.Host;
}
public TestUri(string host)
{
Host = host;
}
private string host;
private string Host
{
get { return host; }
set { host = value; }
}
public string PublicHostNoInline
{
[MethodImpl(MethodImplOptions.NoInlining)]
get { return host; }
[MethodImpl(MethodImplOptions.NoInlining)]
set { host = value; }
}
public string PublicHost
{
get { return host; }
set { host = value; }
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment