zoukankan      html  css  js  c++  java
  • 绕开频繁反射

        在.net里面,反射是一个功能强大的工具,但是,这个强大功能背后却是性能的损失。尤其是频繁的反射,将降低总体性能。
        为了程序运行的更快更好,有必要在频繁反射的地方添加必要的缓存,用尽量少的反射,获得必要的灵活性,而又不降低太多性能。
        说到性能,先说一下在.net中的性能排列吧,最快的是非虚方法,然后依次是虚方法、接口方法,委托,反射。前面3个的性能几乎可以忽略。委托比一般的方法执行要来得慢(可以参考 Why is IComparer an Interface?),而反射,比委托更慢,总之,功能越强的越慢。。。
        因此,绕开频繁反射,将反射方法的调用转化为使用非虚方法、虚方法、接口方法、委托中的任何一种,性能都回提升。
        下面,来看看可行性。
        一、将反射变成委托,虽然提升的比较少,但是也是提升,来看一下如何转换:
        在.net 2.0中引入了一个新的类型,System.Reflection.Emit.DynamicMethod,这个类型可以创建一个动态方法,执行的内容根据GetILGenerator()方法返回的ILGenerator生成的代码,生成代码时把反射得到的MethodInfo放进去就可以了,再通过Delegate CreateDelegate(Type delegateType)返回一个委托,然后,只要去Invoke这个委托就可以了。
        优点:将第一次之后的反射调用,转化为调用委托。
        缺点:第一次执行时,除了反射还需要Emit一个动态方法。而且,每次反射一个不同的方法,就需要一个新的动态方法。
        二、将反射变成接口方法,这个方案可以把性能提高到接近静态代码的程度,来看一下如何实现:
        这次,需要全方位的使用Emit了。
        预备工作:预备一个公开的接口,调用的方法的签名必须和接口中方法一致(通常这条是满足的,如果不满足这条,就不能用这个方案了)。
        类型准备工作:首先需要创建一个动态程序集(可重用),再创建一个动态模块(可重用),创建动态类型,并符合接口,方法的实现部分,只需要调用反射获得的MethodInfo。再准备一个默认的构造函数。
        获得接口实例:创建出这个类型的一个实例,as成接口,用变量保存起来。
        以后,每次调用的时候,只需要调用接口的函数就可以了。
        优点:将第一次之后的反射调用,转化为调用接口方法。
        缺点:第一次执行时,除了反射还需要Emit一个完整的动态类型。而且,每次反射一个不同的方法,就需要一个新的动态类型。
        三、将反射变成虚方法,没有必要,就算要实现,和接口方法也差不太多,而且,性能没什么太大的差别,还没有接口灵活。
        四、将反射变成非虚方法,好像没法实现。。。

        这几个方式,都是以第一次的性能为牺牲,换取之后的性能提升。但是问题是,这个时间是否换的划算哪?
        这就要看反射会被调用多少次了,如果,一共才调个10次,显然,还不如直接反射来的快,根本没必要如此吃力不讨好。
        但是如果,是作为服务程序运行,并且会被高频率的反射,那么,这么做就有价值了。

        最后,留下一个更BT的做法,如果还没有对Emit或IL有足够的了解,建议跳过这一段。
        熟悉Emit的应该看到过Opcodes.Calli,按照MSDN上的说法,它会调用堆栈上的IntPtr所指向的函数,也就是说,只要获得某个方法的指针,就可以用这个Calli去掉用这个方法。问题变成如何获得这个方法的指针,虽然Opcodes.Ldftn和Opcodes.Ldvirtftn可以获得这个指针,但是显然,这样就没意义了(C#,VB.Net好像都没有提供这个方法的直接调用,要是为每一个反射建一个动态类型=没有改进。。。),从反射这里,仔细看一下System.Reflection.MethodBase,可以找到一个叫MethodHandle的属性,返回了一个RuntimeMethodHandle的结构体,而这个结构体提供了一个IntPtr GetFuntionPoint()的方法,它返回的指针就是Opcodes.Calli所需要的指针。再之后,我也不用说了,开始向C的函数指针靠拢。。。
  • 相关阅读:
    windows7修改双系统启动项名称、先后顺序、等待时间
    windows初始化后做了哪些事情
    我的wordpress插件总结
    分析MySQL慢日志(转)
    在Java中使用Memcached(转)
    memcached应用场景(转)
    memcached简介(转)
    Linux下memcache的安装和启动(转)
    列式数据库
    Android测试(一):在Android中测试App
  • 原文地址:https://www.cnblogs.com/vwxyzh/p/781859.html
Copyright © 2011-2022 走看看