優化委托的 Intro 委托方法里有一個 的方法,可以在不清楚委托實際類型的情況下執行委托方法,但是用 去執行的話會比直接用 的方法會慢上很多,差了兩個數量級,所以在知道委托類型的情況下儘可能使用 執行,但有時候我們並不知道委托的實際類型,比如在很多類庫項目中可能並不是強類型的委托 優化方法 優化方 ...
優化委托的 DynamicInvoke
Intro
委托方法里有一個 DynamicInvoke
的方法,可以在不清楚委托實際類型的情況下執行委托方法,但是用 DynamicInvoke
去執行的話會比直接用 Invoke
的方法會慢上很多,差了兩個數量級,所以在知道委托類型的情況下儘可能使用 Invoke
執行,但有時候我們並不知道委托的實際類型,比如在很多類庫項目中可能並不是強類型的委托
優化方法
優化方法,直接執行委托的對應的方法,DynamicInvoke
實際也是調用的對應的方法,我們如果執行調用對應的方法就可以優化
delegate func = (Func<string, string>)str=> "12345";
string paramString = "321";
// Invoke
((Func<string, string>)func).Invoke(paramString);
// DynamicInvoke
func.DynamicInvoke(new object[]{ paramString });
// Method Invoke
func.Method.Invoke(func.Target, new object[]{ paramString });
性能測試
下麵做一個性能測試,測試代碼如下:
public class DelegateInvokeTest
{
private readonly Delegate _func, _func1;
private readonly string parameter;
private readonly int paramInt;
public DelegateInvokeTest()
{
parameter = "Test";
paramInt = 1;
_func = (Func<string, string>)(str => str);
_func1 = (Func<int, int>)(val => 0);
}
[Benchmark(Baseline = true)]
public object Invoke()
{
return ((Func<string, string>)_func).Invoke(parameter);
}
[Benchmark]
public object InvokeBoxing()
{
return ((Func<int, int>)_func1).Invoke(paramInt);
}
[Benchmark]
public object DynamicInvoke()
{
return _func.DynamicInvoke(parameter);
}
[Benchmark]
public object DynamicInvokeBoxing()
{
return _func1.DynamicInvoke(paramInt);
}
[Benchmark]
public object MethodInfoInvoke()
{
return _func.Method?.Invoke(_func.Target, new object[] { parameter });
}
[Benchmark]
public object MethodInfoInvokeBoxing()
{
return _func1.Method?.Invoke(_func1.Target, new object[] { paramInt });
}
[Benchmark]
public object ReflectInvoke()
{
var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(string));
var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func) as MethodInfo;
var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func);
return method?.Invoke(target, new object[] { parameter });
}
[Benchmark]
public object ReflectInvokeBoxing()
{
var funcType = typeof(Func<,>).MakeGenericType(typeof(string), typeof(int));
var method = funcType.GetProperty("Method")?.GetValueGetter()?.Invoke(_func1) as MethodInfo;
var target = funcType.GetProperty("Target")?.GetValueGetter()?.Invoke(_func1);
return method?.Invoke(target, new object[] { paramInt });
}
}
測試結果如下:
由上面的結果,我們可以看出來,直接調用方法的性能雖然還是比 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