大数跨境
0
0

优化委托的 DynamicInvoke

优化委托的 DynamicInvoke amazingdotnet
2020-04-19
0
导读:委托的 DynamicInvoke 小优化

优化委托的 DynamicInvoke

Intro

委托方法里有一个 DynamicInvoke 的方法,可以在不清楚委托实际类型的情况下执行委托方法,但是用 DynamicInvoke 去执行的话会比直接用 Invoke 的方法会慢上很多,差了两个数量级,所以在知道委托类型的情况下尽可能使用 Invoke 执行,但有时候我们并不知道委托的实际类型,比如在很多类库项目中可能并不是强类型的委托

优化方法

优化方法,直接执行委托的对应的方法, DynamicInvoke 实际也是调用的对应的方法,我们如果执行调用对应的方法就可以优化

 
  1. delegate func = (Func<string, string>)str=> "12345";

  2. string paramString = "321";


  3. // Invoke

  4. ((Func<string, string>)func).Invoke(paramString);


  5. // DynamicInvoke

  6. func.DynamicInvoke(new object[]{ paramString });


  7. // Method Invoke

  8. func.Method.Invoke(func.Target, new object[]{ paramString });

性能测试

下面做一个性能测试,测试代码如下:

 
  1. public class DelegateInvokeTest

  2. {

  3. private readonly Delegate _func, _func1;

  4. private readonly string parameter;

  5. private readonly int paramInt;


  6. public DelegateInvokeTest()

  7. {

  8. parameter = "Test";

  9. paramInt = 1;


  10. _func = (Func<string, string>)(str => str);

  11. _func1 = (Func<int, int>)(val => 0);

  12. }


  13. [Benchmark(Baseline = true)]

  14. public object Invoke()

  15. {

  16. return ((Func<string, string>)_func).Invoke(parameter);

  17. }


  18. [Benchmark]

  19. public object InvokeBoxing()

  20. {

  21. return ((Func<int, int>)_func1).Invoke(paramInt);

  22. }


  23. [Benchmark]

  24. public object DynamicInvoke()

  25. {

  26. return _func.DynamicInvoke(parameter);

  27. }


  28. [Benchmark]

  29. public object DynamicInvokeBoxing()

  30. {

  31. return _func1.DynamicInvoke(paramInt);

  32. }


  33. [Benchmark]

  34. public object MethodInfoInvoke()

  35. {

  36. return _func.Method?.Invoke(_func.Target, new object[] { parameter });

  37. }


  38. [Benchmark]

  39. public object MethodInfoInvokeBoxing()

  40. {

  41. return _func1.Method?.Invoke(_func1.Target, new object[] { paramInt });

  42. }


  43. [Benchmark]

  44. public object ReflectInvoke()

  45. {

  46. var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(string));

  47. var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func) as MethodInfo;

  48. var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func);

  49. return method?.Invoke(target, new object[] { parameter });

  50. }


  51. [Benchmark]

  52. public object ReflectInvokeBoxing()

  53. {

  54. var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(int));

  55. var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func1) as MethodInfo;

  56. var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func1);

  57. return method?.Invoke(target, new object[] { paramInt });

  58. }

  59. }

测试结果如下:

由上面的结果,我们可以看出来,直接调用方法的性能虽然还是比 Invoke 慢上好多,但是相比 DynamicInvoke 已经优化 70% 左右,对于有装箱操作的性能会稍差一些,比 DynamicInvoke 优化可达 44% 左右。

Reference

  • https://github.com/WeihanLi/PerformanceTest/blob/master/PerformanceTest/ReflectionTests/DelegateInvokeTest.cs

  • https://github.com/WeihanLi/PerformanceTest/blob/master/PerformanceTest/BenchmarkDotNet.Artifacts/results/PerformanceTest.ReflectionTests.DelegateInvokeTest-report-github.md


【声明】内容源于网络
0
0
amazingdotnet
dotnet 开发知识库,了不起的 dotnet,dotnet 奇淫怪巧
内容 539
粉丝 0
amazingdotnet dotnet 开发知识库,了不起的 dotnet,dotnet 奇淫怪巧
总阅读212
粉丝0
内容539