100,000 calls, 20 test iterations, x86 | 100,000 calls, 20 test iterations, x64 | 1,000,000 calls, 10 test iterations, x86 | 1,000,000 calls, 10 test iterations, x64 | |
---|---|---|---|---|
Direct call | Min: 1 ms Max: 1 ms Mean: 1 ms Median: 1 ms Abs: 1 | Min: 1 ms Max: 1 ms Mean: 1 ms Median: 1 ms Abs: 1 | Min: 7 ms Max: 8 ms Mean: 7.5 ms Median: 7.5 ms Abs: 1 | Min: 5 ms Max: 6 ms Mean: 5.2 ms Median: 5 ms Abs: 1 |
Call through reflection | Min: 32 ms Max: 36 ms Mean: 32.75 ms Median: 32.5 ms Rel: 32 | Min: 35 ms Max: 44 ms Mean: 36.5 ms Median: 36 ms Rel: 36 | Min: 333 ms Max: 399 ms Mean: 345.5 ms Median: 338 ms Rel: 45 | Min: 362 ms Max: 385 ms Mean: 373.6 ms Median: 376 ms Rel: 75 |
Call via delegate | Min: 64 ms Max: 71 ms Mean: 65.05 ms Median: 64,5 ms Rel: 64 | Min: 72 ms Max: 86 ms Mean: 75.95 ms Median: 75 ms Rel: 75 | Min: 659 ms Max: 730 ms Mean: 688.8 ms Median: 689,5 ms Rel: 92 | Min: 746 ms Max: 869 ms Mean: 773.4 ms Median: 765 ms Rel: 153 |
Call via delegate with optimizations | Min: 16 ms Max: 18 ms Mean: 16.2 ms Median: 16 ms Rel: 16 | Min: 21 ms Max: 25 ms Mean: 22.15 ms Median: 22 ms Rel: 22 | Min: 168 ms Max: 187 ms Mean: 172.8 ms Median: 170,5 ms Rel: 22.7 | Min: 218 ms Max: 245 ms Mean: 228.8 ms Median: 227 ms Rel: 45.4 |
Call via dynamic | Min: 11 ms Max: 14 ms Mean: 11.5 ms Median: 11 ms Rel: 11 | Min: 12 ms Max: 14 ms Mean: 12.5 ms Median: 12 ms Rel: 12 | Min: 124 ms Max: 147 ms Mean: 132.1 ms Median: 130 ms Rel: 17 | Min: 127 ms Max: 144 ms Mean: 131.5 ms Median: 129,5 ms Rel: 26 |
Call via Expression | Min: 4 ms Max: 4 ms Mean: 4 ms Median: 4 ms Rel: 4 | Min: 4 ms Max: 5 ms Mean: 4.15 ms Median: 4 ms Rel: 4 | Min: 46 ms Max: 55 ms Mean: 50 ms Median: 50,5 ms Rel: 6.7 | Min: 47 ms Max: 51 ms Mean: 47.7 ms Median: 47 ms Rel: 9.4 |
class SampleGeneric<T> { public long Process(T obj) { return String.Format("{0} [{1}]", obj.ToString(), obj.GetType().FullName).Length; } } class Container { private static Dictionary<Type, object> _instances = new Dictionary<Type, object>(); public static void Register<T>(SampleGeneric<T> instance) { if (false == _instances.ContainsKey(typeof(T))) { _instances.Add(typeof(T), instance); } else { _instances[typeof(T)] = instance; } } public static SampleGeneric<T> Get<T>() { if (false == _instances.ContainsKey(typeof(T))) throw new KeyNotFoundException(); return (SampleGeneric<T>)_instances[typeof(T)]; } public static object Get(Type type) { if (false == _instances.ContainsKey(type)) throw new KeyNotFoundException(); return _instances[type]; } }
public interface ISampleGeneric { } class SampleGeneric<T> : ISampleGeneric // private static Dictionary<Type, ISampleGeneric> _instances = new Dictionary<Type, ISampleGeneric>();
// Type expected Dictionary<Type, SampleGeneric<>>
typeof(SampleGeneric<>).MakeGenericType(typeof(string))
void NonGenericMethod(object obj) { var handler = Container.Get(obj.GetType()); }
Container.GetInstance<fromtype(obj.GetType())>().Process(obj);
public static TestResult TestDirectCall(DateTime arg) { var instance = Container.Get<DateTime>(); long summ = 0; for (long i = 0; i < ITERATION_COUNT; i++) { summ += instance.Process(arg); } // return }
public static TestResult TestReflectionCall(object arg) { var instance = Container.Get(arg.GetType()); var method = instance.GetType().GetMethod("Process"); long summ = 0; for (long i = 0; i < ITERATION_COUNT; i++) { summ += (long)method.Invoke(instance, new object[] { arg }); } // return }
private static Delegate CreateDelegate(object target, MethodInfo method) { var methodParameters = method.GetParameters(); var arguments = methodParameters.Select(d => Expression.Parameter(d.ParameterType, d.Name)).ToArray(); var instance = target == null ? null : Expression.Constant(target); var methodCall = Expression.Call(instance, method, arguments); return Expression.Lambda(methodCall, arguments).Compile(); }
public static TestResult TestDelegateCall(object arg) { var instance = Container.Get(arg.GetType()); var hook = CreateDelegate(instance, instance.GetType().GetMethod("Process")); long summ = 0; for (long i = 0; i < ITERATION_COUNT; i++) { summ += (long)hook.DynamicInvoke(arg); } // return }
internal static object FastDynamicInvokeDelegate(Delegate del, params dynamic[] args) { dynamic tDel = del; switch (args.Length) { default: try { return del.DynamicInvoke(args); } catch (TargetInvocationException ex) { throw ex.InnerException; } #region Optimization case 1: return tDel(args[0]); case 2: return tDel(args[0], args[1]); case 3: return tDel(args[0], args[1], args[2]); case 4: return tDel(args[0], args[1], args[2], args[3]); case 5: return tDel(args[0], args[1], args[2], args[3], args[4]); case 6: return tDel(args[0], args[1], args[2], args[3], args[4], args[5]); case 7: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); case 8: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); case 9: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); case 10: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); case 11: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); case 12: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); case 13: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]); case 14: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]); case 15: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14]); case 16: return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15]); #endregion } }
public static TestResult TestDelegateOptimizeCall(object arg) { var instance = Container.Get(arg.GetType()); var hook = CreateDelegate(instance, instance.GetType().GetMethod("Process")); long summ = 0; for (long i = 0; i < ITERATION_COUNT; i++) { summ += (long)FastDynamicInvokeDelegate(hook, arg); } // return }
public static TestResult TestDynamicCall(dynamic arg) { var instance = Container.Get(arg.GetType()); dynamic hook = CreateDelegate(instance, instance.GetType().GetMethod("Process")); long summ = 0; for (long i = 0; i < ITERATION_COUNT; i++) { summ += hook(arg); } // return }
delegate object Invoker(object target, params object[] args); static Invoker CreateExpression(MethodInfo method) { var targetArg = Expression.Parameter(typeof(object)); var argsArg = Expression.Parameter(typeof(object[])); Expression body = Expression.Call( method.IsStatic ? null : Expression.Convert(targetArg, method.DeclaringType), method, method.GetParameters().Select((p, i) => Expression.Convert(Expression.ArrayIndex(argsArg, Expression.Constant(i)), p.ParameterType))); if (body.Type == typeof(void)) body = Expression.Block(body, Expression.Constant(null)); else if (body.Type.IsValueType) body = Expression.Convert(body, typeof(object)); return Expression.Lambda<Invoker>(body, targetArg, argsArg).Compile(); }
public static TestResult TestExpressionCall(object arg) { var instance = Container.Get(arg.GetType()); var hook = CreateExpression(instance.GetType().GetMethod("Process")); long summ = 0; for (long i = 0; i < ITERATION_COUNT; i++) { summ += (long)hook(instance, arg); } //return }
Source: https://habr.com/ru/post/279367/
All Articles