当前位置: 移动技术网 > IT编程>开发语言>c# > 优化委托的 `DynamicInvoke`

优化委托的 `DynamicInvoke`

2020年04月20日  | 移动技术网IT编程  | 我要评论

优化委托的 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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网