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

委托的 `DynamicInvoke` 小优化的更多相关文章

  1. SPFA 小优化*2

    /* bzoj 2763 SPFA小优化 循环队列+SLF 顺面改掉自己之前手打qeueu的坏毛病*/ #include<iostream> #include<cstring> ...

  2. 缓存 Array.length 是老生常谈的小优化

    问题 缓存 Array.length 是老生常谈的小优化. // 不缓存 for (var i = 0; i < arr.length; i++) { ... } // 缓存 var len = ...

  3. [MySQL5.6] 最近对group commit的小优化

    [MySQL5.6] 最近对group commit的小优化 http://www.tuicool.com/articles/rEZr2q 最近花了一些时间在做MySQL Group Commit的优 ...

  4. SPFA的小优化

    标签:闲扯 SPFA的小优化 1. 向队尾加入元素时,如果它比对首还优,就把把它直接和队首交换. 拿一个双端队列来实现 (手写 , head ,tail   STLdeque亲测及其慢) 这个小优化其 ...

  5. KMP算法的正确性证明及一个小优化

    直接把作业帖上来是不是有点不太公道呀... 无所谓啦反正各位看着开心就行 KMP算法 对于模式串$P$,建立其前缀函数$ N$ ,其中$N [q] $ 表示在$P$中,以$q$位置为结束的可以匹配到前 ...

  6. js代码小优化

    今天真坑,老大请了两天假,来了之后指指点点,不过人家说的倒是很是到位 好不容易把嵌套小窗口登陆注册功能,做完了,直接调之前写好的登陆注册功能,也就是页面跳转 并不是ajax异步登陆 说让改成ajax ...

  7. HDU 5884 Sort(2016年青岛网络赛 G 二分+贪心+小优化)

    好题 题意:给你n<=100000个数,每个数范围[0,1000],然后给你一个最大的代价T,每次最多合并k个数成为一个数,代价为k个数的总和.问最后合成1个数的总代价不大于T的最小k 题解:我 ...

  8. Centos7安装完成后一些小优化

    1.修改ip地址.网关.主机名.DNS等 [root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 #网 ...

  9. UWP自动填充控件AutoSuggestBox小优化

    UWP提供的AutoSuggestBox本身非常好用,在项目中经常用到,但是当我们使用时发现一下不人性化的设置,例子1如下: <Page x:Class="SelfInkCanvas. ...

随机推荐

  1. MySQL基础知识_1

    平时只会使用简单的增删改查,促使我学习这个来源于一道面试题,左思右想,依然想不出来,所以决定系统的学习一下. MySQL创建数据库 CREATE DATABASE <数据库名>; CREA ...

  2. kali的安装详解--摘自官方

    官方网址:https://www.kali.org/docs/virtualization/install-vmware-workstation-player-kali-guest-vm/ 在VMwa ...

  3. Springboot CORS跨域访问

    Springboot CORS跨域访问 什么是跨域 浏览器的同源策略限制: 它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础 ...

  4. Jocke的IOT之路--raspberrypi更换国内镜像

    一.编辑sources.list文件 sudo nano /etc/apt/sources.list 使用#将文件内容全部注释调,更改位 deb http://mirrors.tuna.tsinghu ...

  5. pat 乙级 1015. 德才论 (25) c++

     http://39.106.25.239 个人网站 欢迎访问 交流 1015. 德才论 (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Sta ...

  6. iphone ios app互相调用

    正好要做这个,记录一下 1.ios应用程序间互相启动 2.网页如何调用自己的app http://www.dotblogs.com.tw/yang5664/archive/2012/11/24/850 ...

  7. Ali_Cloud++:安装 RabbitMQ安装及环境配置

    注意事项:rabbitMA版本和erlang并不是同步更新的,会出现版本不匹配,安装不了. 两都版本对应   参考官网文档    其它下载地址 1):Erlang安装 (因为是erlant语言编写的, ...

  8. VRRP协议:Virtual Route

    VRRP协议:Virtual Route  Redundancy Protocol虚拟路由冗余协议.是一种容错协议,保证当主机的下一跳路由出现故障时,由另一台路由器来代替出现故障的路由器进行工作,从而 ...

  9. iOS 真机查看沙盒目录

    iExplorer 的方法试的时候设备都无法检测到,建议放弃 启用iTunes文件共享,才能够看沙盒内的文件,只需要在plist文件中添加如下信息: <key>UIFileSharingE ...

  10. Python math库和random库

    1.math库 >>> from math import * >>> 2*pi 6.283185307179586 >>> e 2.7182818 ...