.NET创建委托可大幅度提高反射调用的性能

原作者:吕毅
参考地址:https://blog.walterlv.com/post/create-delegate-to-improve-reflection-performance.html
文章内容提炼
1、其实当小数据量情况下,性能损失其实可以忽略不计。
文章内是以10000000循环来测试性能情况。
在常见场景中,比如解耦合项目当中,需要通过反射程序集在Program启动代码中来使用一些方法注册服务或者写中间件,
使用反射通常是一次性操作,这种情况下性能损失非常小。
2、个人认为在频繁调用外部程序集方法的情况下确实可以使用此文章中方法以提高程序调用方法的性能。
  1 // 调用的目标实例。
  2 using System.Diagnostics;
  3 using System.Diagnostics.Contracts;
  4 using System.Reflection;
  5 
  6 var instance = new StubClass();
  7 
  8 // 使用反射找到的方法。
  9 var method = typeof(StubClass).GetMethod(nameof(StubClass.Test), new[] { typeof(int) });
 10 
 11 // 将反射找到的方法创建一个委托。
 12 var func = InstanceMethodBuilder<int, int>.CreateInstanceMethod(instance, method);
 13 
 14 // 跟被测方法功能一样的纯委托。
 15 Func<int, int> pureFunc = value => value;
 16 
 17 // 测试次数。
 18 var count = 10000000;
 19 
 20 // 直接调用。
 21 var watch = new Stopwatch();
 22 watch.Start();
 23 for (var i = 0; i < count; i++)
 24 {
 25     var result = instance.Test(5);
 26 }
 27 
 28 watch.Stop();
 29 Console.WriteLine($"{watch.Elapsed} - {count} 次 - 直接调用");
 30 
 31 // 使用反射创建出来的委托调用。
 32 watch.Restart();
 33 for (var i = 0; i < count; i++)
 34 {
 35     var result = func(5);
 36 }
 37 
 38 watch.Stop();
 39 Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用反射创建出来的委托调用");
 40 
 41 // 使用反射得到的方法缓存调用。
 42 watch.Restart();
 43 for (var i = 0; i < count; i++)
 44 {
 45     var result = method.Invoke(instance, new object[] { 5 });
 46 }
 47 
 48 watch.Stop();
 49 Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用反射得到的方法缓存调用");
 50 
 51 // 直接使用反射调用。
 52 watch.Restart();
 53 for (var i = 0; i < count; i++)
 54 {
 55     var result = typeof(StubClass).GetMethod(nameof(StubClass.Test), new[] { typeof(int) })
 56         ?.Invoke(instance, new object[] { 5 });
 57 }
 58 
 59 watch.Stop();
 60 Console.WriteLine($"{watch.Elapsed} - {count} 次 - 直接使用反射调用");
 61 
 62 /// <summary>
 63 /// 测试方法
 64 /// </summary>
 65 public class StubClass
 66 {
 67     public int Test(int i)
 68     {
 69         return i;
 70     }
 71 }
 72 
 73 /// <summary>
 74 /// 将反射找到的方法创建一个委托
 75 /// </summary>
 76 /// <typeparam name="T"></typeparam>
 77 /// <typeparam name="TReturnValue"></typeparam>
 78 public static class InstanceMethodBuilder<T, TReturnValue>
 79 {
 80     /// <summary>
 81     /// 调用时就像 var result = func(t)。
 82     /// </summary>
 83     [Pure]
 84     public static Func<T, TReturnValue> CreateInstanceMethod<TInstanceType>(TInstanceType instance, MethodInfo method)
 85     {
 86         if (instance == null) throw new ArgumentNullException(nameof(instance));
 87         if (method == null) throw new ArgumentNullException(nameof(method));
 88 
 89         return (Func<T, TReturnValue>)method.CreateDelegate(typeof(Func<T, TReturnValue>), instance);
 90     }
 91 
 92     /// <summary>
 93     /// 调用时就像 var result = func(this, t)。
 94     /// </summary>
 95     [Pure]
 96     public static Func<TInstanceType, T, TReturnValue> CreateMethod<TInstanceType>(MethodInfo method)
 97     {
 98         if (method == null)
 99             throw new ArgumentNullException(nameof(method));
100 
101         return (Func<TInstanceType, T, TReturnValue>)method.CreateDelegate(typeof(Func<TInstanceType, T, TReturnValue>));
102     }
103 }
View Code

 

个人测试结果

 

posted @ 2022-06-14 15:32  塔斯丁狗  阅读(98)  评论(0)    收藏  举报