利用Emit减少反射的性能损失 转.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
利用Emit减少反射的性能损失 转

利用Emit减少反射的性能损失 转 我很喜欢在程序里使用反射,让事情变得更简单、灵活。但是在获得便利的同时带来的是性能上的损失。粗略的测试一下,通过反射根据成员名字去访问成员比直接访问慢250倍左右。听起来挺吓人,但是以时间来算,用我的p4 2.66G的机用反射访问成员一次耗时仅3微秒,对与整个程序的运行周期看来,这占的时间微不足道。 不过我用反射的程度确实过分了点。我很久以前就做过这么一样东西,利用反射实现asp.net控件和数据之间的双向绑定。意料之中的是,有人对我仅为了赋值,取值就使用反射提出质疑。.net阵营不像java那样财大气粗,很多人对性能还是很看重的,风语·深蓝甚至还被上司禁止使用工厂模式,说Activator.CreateInstance会影响性能. 于是,我开始在思考如何减少反射带来的性能损失。首先元数据可以缓存起来,这样就不必重复执行GetTypes(),GetMembers()等方法了,不过这些操作耗时很少,在程序中用到的地方也少,最重要还是要解决如何能快速的通过传入一个对象和对象的属性名去访问属性。要大幅提高性能,唯一办法就是不要用反射。 还能怎样呢?我想到了一个有这样结构的类:这个类有GetValue和SetValue方法,通过一堆case去根据参数去读或写相应的属性,用这种方法就能达到我想要的效果,而又不需要反射了。 但是这样针对每一个类,就要有另一个对应的类去处理这样的事情,所以这些负责Get/Set的类应该在运行时动态生成,这就得靠反射最高级的特性-Emit了。 利用System.Reflection.Emit中的类,可以运行时构造类型,并且通过IL去构造成员。当然,生成C#代码用CodeDom编译也可以,但是速度肯定大打折扣了。 跟着我开始动手,先定义IValueHandler接口: using System; namespace NoReflection { internal interface IValueHandler{ object GetValue(object o,string expression); void SetValue(object o,string expression,object value); object CreateInstance(); } } 然后定义一个叫ObjectUtil类,会用动态构造出用来处理特定类型的IValueHandler的实现类,然后把它放到缓存里。通过几个方法的包装,根据需要调用ValueHandler的GetValue/SetValue。 不要把构造IL想的太恐怖,其实只要对CLI和MSIL有一定的了解,并且能看懂就行了,因为我可以先用熟悉的C#写好代码,编译后再反汇编去看,大部分可以抄。当然这个过程还是花了我很多时间,因为IL里头装箱/拆箱得自己管,不同类型的数据转换的代码又各不相同,然后还发现用short form指令的话如果目标地址的偏移量超过了8位/*双鱼座纠正说是7位.*/就会出错,所以xx.s的指令就不能照抄,统统用xx代替。 拿SqlConnection的处理来举例,动态生成的类是这个样子的: public class ValueHandler:IValueHandler { //Methods public ValueHandler() { } public override object CreateInstance() { return new SqlConnection(); } public override object GetValue(object obj,string property) { switch(property) { caseConnectionString: { return((SqlConnection)obj).ConnectionString; } caseConnectionTimeout: { return((SqlConnection)obj).ConnectionTimeout; } caseDatabase: { return((SqlConnection)obj).Database; } caseDataSource: { return((SqlConnection)obj).DataSource; } casePacketSize: { return((SqlConnection)obj).PacketSize; } caseWorkstationId: { return((SqlConnection)obj).WorkstationId; } caseServerVersion: { return((SqlConnection)obj).ServerVersio

您可能关注的文档

文档评论(0)

2017meng + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档