无为清净楼资源网 Design By www.qnjia.com
可能大家谈到反射面部肌肉都开始抽搐了吧!因为在托管语言里面,最臭名昭著的就是反射!它的性能实在是太低了,甚至在很多时候让我们无法忍受。不过不用那么纠结了,老陈今天就来分享一下如何来优化反射!
概述
本文涉及到的反射优化的途径有如下两种:
通过Delegate.CreateDelegate()创建委托进行优化
通过.NET4的动态运行时进行优化
如果您还知道其他更加有效的优化途径,请不吝赐教!
准备工作
今天我们总计要对比五种不同的调用对象成员的方式,也算是一种性能测评。
在开始之前,我们首先定义一个简单的对象和一个方法,以供测试之用:
复制代码 代码如下:
namespace ReflectionOptimization
{
public sealed class TestObject
{
public int Add(int a, int b)
{
// 简单演示
return a + b;
}
}
}
这个类非常简单,只提供了一个方法,这个方法返回两个整形的和。接下来我们看看执行时间测量的代码,很简单,想必您已经驾轻就熟了:
复制代码 代码如下:
private static double _Run(string description, Action<int, int> action, int a, int b)
{
if (action == null) throw new ArgumentNullException("action");
// 启动计时器
var stopwatch = Stopwatch.StartNew();
// 运行要测量的代码
action(a, b);
// 终止计时
stopwatch.Stop();
// 输出结果
Console.WriteLine("{0}: {1}", description, stopwatch.Elapsed.TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
// 返回执行时间
return stopwatch.Elapsed.TotalMilliseconds;
}
以上测量时间的方法返回了执行时间,因为我们要在后面用到这个值,在执行多次之后取个平均值,以求测试的公平性、权威性。
编码实现
首先我们来看看原生反射的实现:
复制代码 代码如下:
var obj = new TestObject();
var add = obj.GetType().GetMethod("Add");
for (var i = 0; i < _TIMES; i++) add.Invoke(obj, new object[] {a, b});
然后我们看看.NET4动态编程的实现:
复制代码 代码如下:
dynamic obj = new TestObject();
// 有木有发现这个代码超级简单?
for (var i = 0; i < _TIMES; i++) obj.Add(a, b);
最后我们看看如何使用委托来优化反射:
复制代码 代码如下:
// 委托
public delegate int AddMethod(int a, int b);
// 实现
var obj = new TestObject();
var objType = obj.GetType();
var add = objType.GetMethod("Add");
var d = (AddMethod)Delegate.CreateDelegate(typeof(AddMethod), obj, add);
for (var i = 0; i < _TIMES; i++) d(a, b);
上面的代码看起来多了几行,而且还需要自定义一个委托,写起来挺麻烦的。因此我们的测试代码里面还实现了另外一种形式,其实它也是委托:
var d = (Func<TestObject, int, int, int>)Delegate.CreateDelegate(typeof(Func<TestObject, int, int, int>), add);
测试总结
我们首先在Debug模式下将整个测试代码运行5遍,然后分别记录平均值,然后再到Release模式下重复该测试。
测试的过程不再阐述,测试结果整理如下:
调用方式
第一次
第二次
第三次
第四次
第五次
Generic Call
1.022425
1.012885
0.990775
1.020950
1.046880
Reflection
147.489220
146.012010
142.690080
139.189335
141.663475
dynamic
9.645850
9.979965
9.307235
9.532665
9.730030
Func
1.201860
1.214800
1.170215
1.189280
1.239485
Delegate
1.062215
1.061635
1.067510
1.047180
1.075190
调用方式
第一次
第二次
第三次
第四次
第五次
Generic Call
0.745600
0.741365
0.722145
0.732630
0.725645
Reflection
141.778260
142.855410
142.346095
139.649990
138.541285
dynamic
9.631460
10.341850
9.284230
9.457580
9.060470
Func
0.882100
0.852680
0.875695
0.854655
0.831670
Delegate
0.710280
0.722465
0.723355
0.727175
0.693320
代码下载:浅谈反射优化
概述
本文涉及到的反射优化的途径有如下两种:
通过Delegate.CreateDelegate()创建委托进行优化
通过.NET4的动态运行时进行优化
如果您还知道其他更加有效的优化途径,请不吝赐教!
准备工作
今天我们总计要对比五种不同的调用对象成员的方式,也算是一种性能测评。
在开始之前,我们首先定义一个简单的对象和一个方法,以供测试之用:
复制代码 代码如下:
namespace ReflectionOptimization
{
public sealed class TestObject
{
public int Add(int a, int b)
{
// 简单演示
return a + b;
}
}
}
这个类非常简单,只提供了一个方法,这个方法返回两个整形的和。接下来我们看看执行时间测量的代码,很简单,想必您已经驾轻就熟了:
复制代码 代码如下:
private static double _Run(string description, Action<int, int> action, int a, int b)
{
if (action == null) throw new ArgumentNullException("action");
// 启动计时器
var stopwatch = Stopwatch.StartNew();
// 运行要测量的代码
action(a, b);
// 终止计时
stopwatch.Stop();
// 输出结果
Console.WriteLine("{0}: {1}", description, stopwatch.Elapsed.TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
// 返回执行时间
return stopwatch.Elapsed.TotalMilliseconds;
}
以上测量时间的方法返回了执行时间,因为我们要在后面用到这个值,在执行多次之后取个平均值,以求测试的公平性、权威性。
编码实现
首先我们来看看原生反射的实现:
复制代码 代码如下:
var obj = new TestObject();
var add = obj.GetType().GetMethod("Add");
for (var i = 0; i < _TIMES; i++) add.Invoke(obj, new object[] {a, b});
然后我们看看.NET4动态编程的实现:
复制代码 代码如下:
dynamic obj = new TestObject();
// 有木有发现这个代码超级简单?
for (var i = 0; i < _TIMES; i++) obj.Add(a, b);
最后我们看看如何使用委托来优化反射:
复制代码 代码如下:
// 委托
public delegate int AddMethod(int a, int b);
// 实现
var obj = new TestObject();
var objType = obj.GetType();
var add = objType.GetMethod("Add");
var d = (AddMethod)Delegate.CreateDelegate(typeof(AddMethod), obj, add);
for (var i = 0; i < _TIMES; i++) d(a, b);
上面的代码看起来多了几行,而且还需要自定义一个委托,写起来挺麻烦的。因此我们的测试代码里面还实现了另外一种形式,其实它也是委托:
var d = (Func<TestObject, int, int, int>)Delegate.CreateDelegate(typeof(Func<TestObject, int, int, int>), add);
测试总结
我们首先在Debug模式下将整个测试代码运行5遍,然后分别记录平均值,然后再到Release模式下重复该测试。
测试的过程不再阐述,测试结果整理如下:
Debug模式:
Release模式:
点评&结论:
- 使用委托优化反射之后,其性能与直接调用相差无几,保持在同一个数量级之内,对性能要求极度苛刻时推荐此方案;
- 显式委托(Delegate)和匿名委托(Func)性能差异非常不明显,但显式委托的性能还是好一点;
- 原生委托比直接调用慢出了两个数量级,性能差异达到了200倍之多!
- .NET 4的动态编程语法相当简洁,其性能只比直接调用高出一个数量级,由于其语法相当简洁,我们推荐这种做法!
- 原生反射技术在Debug模式和Release模式下没有太大差异,但其他方式有较为明显的优化效果(请思考为什么);
- 虽然我们今天的测试不能完全意味着反射优化之后可以和直接调用相媲美,但至少可以从某种程度上击败那些个谣言——谁说反射就一定会慢(嘻嘻)!
代码下载:浅谈反射优化
标签:
.NET,反射机制
无为清净楼资源网 Design By www.qnjia.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
无为清净楼资源网 Design By www.qnjia.com
暂无评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
2024年11月19日
2024年11月19日
- 好薇2024《兵哥哥》1:124K黄金母盘[WAV+CUE]
- 胡歌.2006-珍惜(EP)【步升大风】【FLAC分轨】
- 洪荣宏.2014-拼乎自己看【华特】【WAV+CUE】
- 伊能静.1999-从脆弱到勇敢1987-1996精选2CD【华纳】【WAV+CUE】
- 刘亮鹭《汽车DJ玩主》[WAV+CUE][1.1G]
- 张杰《最接近天堂的地方》天娱传媒[WAV+CUE][1.1G]
- 群星《2022年度发烧天碟》无损黑胶碟 2CD[WAV+CUE][1.4G]
- 罗文1983-罗文甄妮-射雕英雄传(纯银AMCD)[WAV+CUE]
- 群星《亚洲故事香港纯弦》雨果UPMAGCD2024[低速原抓WAV+CUE]
- 群星《经典咏流传》限量1:1母盘直刻[低速原抓WAV+CUE]
- 庾澄庆1993《老实情歌》福茂唱片[WAV+CUE][1G]
- 许巍《在别处》美卡首版[WAV+CUE][1G]
- 林子祥《单手拍掌》华纳香港版[WAV+CUE][1G]
- 郑秀文.1997-我们的主题曲【华纳】【WAV+CUE】
- 群星.2001-生命因爱动听电影原创音乐AVCD【MEDIA】【WAV+CUE】