欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

优化委托的 `DynamicInvoke`

程序员文章站 2022-05-03 23:00:02
优化委托的 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 });
    }
}

测试结果如下:

优化委托的 `DynamicInvoke`

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

reference