委托的 `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
- https://github.com/WeihanLi/PerformanceTest/blob/master/PerformanceTest/ReflectionTests/DelegateInvokeTest.cs
- https://github.com/WeihanLi/PerformanceTest/blob/master/PerformanceTest/BenchmarkDotNet.Artifacts/results/PerformanceTest.ReflectionTests.DelegateInvokeTest-report-github.md
委托的 `DynamicInvoke` 小优化的更多相关文章
- SPFA 小优化*2
/* bzoj 2763 SPFA小优化 循环队列+SLF 顺面改掉自己之前手打qeueu的坏毛病*/ #include<iostream> #include<cstring> ...
- 缓存 Array.length 是老生常谈的小优化
问题 缓存 Array.length 是老生常谈的小优化. // 不缓存 for (var i = 0; i < arr.length; i++) { ... } // 缓存 var len = ...
- [MySQL5.6] 最近对group commit的小优化
[MySQL5.6] 最近对group commit的小优化 http://www.tuicool.com/articles/rEZr2q 最近花了一些时间在做MySQL Group Commit的优 ...
- SPFA的小优化
标签:闲扯 SPFA的小优化 1. 向队尾加入元素时,如果它比对首还优,就把把它直接和队首交换. 拿一个双端队列来实现 (手写 , head ,tail STLdeque亲测及其慢) 这个小优化其 ...
- KMP算法的正确性证明及一个小优化
直接把作业帖上来是不是有点不太公道呀... 无所谓啦反正各位看着开心就行 KMP算法 对于模式串$P$,建立其前缀函数$ N$ ,其中$N [q] $ 表示在$P$中,以$q$位置为结束的可以匹配到前 ...
- js代码小优化
今天真坑,老大请了两天假,来了之后指指点点,不过人家说的倒是很是到位 好不容易把嵌套小窗口登陆注册功能,做完了,直接调之前写好的登陆注册功能,也就是页面跳转 并不是ajax异步登陆 说让改成ajax ...
- HDU 5884 Sort(2016年青岛网络赛 G 二分+贪心+小优化)
好题 题意:给你n<=100000个数,每个数范围[0,1000],然后给你一个最大的代价T,每次最多合并k个数成为一个数,代价为k个数的总和.问最后合成1个数的总代价不大于T的最小k 题解:我 ...
- Centos7安装完成后一些小优化
1.修改ip地址.网关.主机名.DNS等 [root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 #网 ...
- UWP自动填充控件AutoSuggestBox小优化
UWP提供的AutoSuggestBox本身非常好用,在项目中经常用到,但是当我们使用时发现一下不人性化的设置,例子1如下: <Page x:Class="SelfInkCanvas. ...
随机推荐
- Journal of Proteomics Research | Th-MYCN转基因小鼠的定量蛋白质学分析揭示了Aurora Kinase抑制剂改变代谢途径和增强ACADM以抑制神经母细胞瘤的进展
题目:Quantitative Proteomics of Th-MYCN Transgenic Mice Reveals Aurora Kinase Inhibitor Altered Metabo ...
- 面试刷题12:zero copy是怎么回事?
文件copy是java的io部分不可忽视的内容. 我是李福春,我在准备面试,今天的问题是: zero-copy是怎么回事? 操作系统的空间划分为内核态空间, 用户态空间: 内核态空间相对操作系统具备更 ...
- Cisco 综合配置(三)
要求: 1.PC1 PC2使用DHCP,获取IP ,VLAN为10 和20,网关在Core Switch 2上2.DHCP和web server VLAN为100,网关在Core Switch 1上3 ...
- 解析“60k”大佬的19道C#面试题(上)
解析"60k"大佬的19道C#面试题(上) 先略看题目: 请简述async函数的编译方式 请简述Task状态机的实现和工作机制 请简述await的作用和原理,并说明和GetResu ...
- 彻底明白equals和hashCode
equals和hashCode方法 equals 我们知道equals是用来比较两个对象是否相等的,比如我们常用的String.equals方法 @Test public void test() { ...
- selenium 使用教程详解-java版本
第一章 Selenium 概述 1.1.Selenium 发展史 Selenium是一系列基于Web的自动化工具,提供一套测试函数,用于支持Web自动化测试.函数非常灵活,能够完成界面元素定位.窗 ...
- Django-rest-framework源码分析(二)
四.Serializer对象的data属性 在<Django-rest-framework源码分析(一)>中我分析了Serializer对象实例化的过程,而Serializer类的其他方法 ...
- JavaScript实现图结构
JavaScript实现图结构 一.图论 1.1.图的简介 什么是图? 图结构是一种与树结构有些相似的数据结构: 图论是数学的一个分支,并且,在数学中,树是图的一种: 图论以图为研究对象,研究顶点和边 ...
- Flutter 不可错过的学习资源
老孟导读:今天给大家分享一下我在学习Flutter的过程中整理的资料,这些文章或者开源项目都是精挑细选的,希望可以帮助到到家.另外相关资料会在Github一直更新,欢迎大家fork,如果喜欢的话给个小 ...
- ajax请求以及递归
function f1() { console.log("hello"); f1(); }; f1();//浏览器崩溃,因为没有结束条件——死循环 改进如下: var i=0; f ...