優(yōu)化委托的 DynamicInvoke
Intro
委托方法里有一個(gè) DynamicInvoke
的方法困曙,可以在不清楚委托實(shí)際類型的情況下執(zhí)行委托方法乳蓄,但是用 DynamicInvoke
去執(zhí)行的話會(huì)比直接用 Invoke
的方法會(huì)慢上很多敞斋,差了兩個(gè)數(shù)量級(jí)黄虱,所以在知道委托類型的情況下盡可能使用 Invoke
執(zhí)行疤剑,但有時(shí)候我們并不知道委托的實(shí)際類型砸狞,比如在很多類庫項(xiàng)目中可能并不是強(qiáng)類型的委托
優(yōu)化方法
優(yōu)化方法,直接執(zhí)行委托的對(duì)應(yīng)的方法,DynamicInvoke
實(shí)際也是調(diào)用的對(duì)應(yīng)的方法虹茶,我們?nèi)绻麍?zhí)行調(diào)用對(duì)應(yīng)的方法就可以優(yōu)化
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 });
性能測(cè)試
下面做一個(gè)性能測(cè)試逝薪,測(cè)試代碼如下:
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 });
}
}
測(cè)試結(jié)果如下:
測(cè)試結(jié)果
由上面的結(jié)果,我們可以看出來蝴罪,直接調(diào)用方法的性能雖然還是比 Invoke
慢上好多董济,但是相比 DynamicInvoke
已經(jīng)優(yōu)化 70% 左右,對(duì)于有裝箱操作的性能會(huì)稍差一些要门,比 DynamicInvoke
優(yōu)化可達(dá) 44% 左右虏肾。