• 优化委托的 `DynamicInvoke`


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

  • 相关阅读:
    windows10上安装 .NET Framework 3.5
    Mac上安装Tomcat服务器
    实验室中搭建Spark集群和PyCUDA开发环境
    训练实录
    Hello World
    存储管理
    java脚本实现selenium架构下的复选框、上传文件的操作
    java脚本,selenium工具,自动发QQ邮件
    用java脚本,selenium2.0工具,切换窗口经验总结
    六、排队论模型
  • 原文地址:https://www.cnblogs.com/weihanli/p/12732737.html
Copyright © 2020-2023  润新知