`
影梦龙
  • 浏览: 124346 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
文章分类
社区版块
存档分类
最新评论

Fast Reflection Library

阅读更多

摘至:http://www.cnblogs.com/JeffreyZhao/archive/2009/02/01/Fast-Reflection-Library.html

基本使用方式
  反射是.NET中非常重要的功能。使用反射来构造对象、调用方法或是访问属性是某些项目中常用的做法之一(例如ORM框架)。众所周知,与一个成员的直接访问相比,反射调用的性能要低好几个数量级。FastReflectionLib提供了一种简便的方式,使一些常用反射调用的性能得到大幅提高。如下:

using System;using System.Reflection;using FastReflectionLib;namespace SimpleConsole{class Program{static void Main(string[] args)        {PropertyInfo propertyInfo = typeof(string).GetProperty("Length");MethodInfo methodInfo = typeof(string).GetMethod("Contains");string s = "Hello World!";// get value by normal reflectionint length1 = (int)propertyInfo.GetValue(s, null);// get value by the extension method from FastReflectionLib,            // which is much fasterint length2 = (int)propertyInfo.FastGetValue(s);// invoke by normal reflectionbool result1 = (bool)methodInfo.Invoke(s, new object[] { "Hello" });// invoke by the extension method from FastReflectionLib,            // which is much fasterbool result2 = (bool)methodInfo.FastInvoke(s, new object[] { "Hello" });        }    }}
  在得到了PropertyInfo或MethodInfo对象之后,我们可以使用GetValue或Invoke方法来访问属性或调用方法。在 FastReflectionLib中为PropertyInfo、MethodInfo等对象定义了对应的扩展方法,于是我们就可以使用这些扩展方法(从代码上看来,基本上只是在原来的方法之前加上“Fast”)来进行调用,与之前的方法相比,新的扩展方法性能有极大的提高。

直接使用各工作对象
  各FastXxx方法实际上是将PropertyInfo等对象作为Key去一个Cache中获取对应的工作对象,然后调用工作对象上对应的方法。因此,直接调用工作对象可以获得更好的性能。各工作对象类型的对应关系如下:

PropertyInfo:IPropertyAccessor
MethodInfo:IMethodInvoker
ConstructorInfo:IConstructorInvoker
FieldInfo:IFieldAccessor
  我们可以使用FastReflectionCaches.MethodInvokerCache来获取一个IMethodInvoker对象:

static void Execute(MethodInfo methodInfo, object instance, int times){ IMethodInvoker invoker = FastReflectionCaches.MethodInvokerCache.Get(methodInfo);object[] parameters = new object[0];for (int i = 0; i < times; i++)    {        invoker.Invoke(instance, parameters);    }}
工作对象的默认实现与扩展
  在FastReflectionLib中,已经提供了IPropertyAccessor等接口的默认实现。该实现将会构造一颗表达式树(Expression Tree)并将其编译(调用其Compile方法)以获得一个与反射方法签名相同的委托对象。这是一种简单、通用而安全的实现,由于Compile方法使用了Emit,其性能也较为令人满意(可见下面的性能测试)。但是这并不是性能最高的做法,如果使用Emit生成最优化的代码,其性能甚至会高于方法的直接调用(例如Dynamic Reflection Library)。如果您想使用更好的实现来替换,则可以自行构造一个工作对象接口的实现,并替换对应的Factory:

public class BetterPropertyAccessor : IPropertyAccessor{public BetterPropertyAccessor(PropertyInfo propertyInfo) { ... }    ...}public class BetterPropertyAccessorFactory :IFastReflectionFactory<PropertyInfo, IPropertyAccessor>{public IPropertyAccessor Create(PropertyInfo key)    {return new BetterPropertyAccessor(key);    }}class Program{static void Main(string[] args)    {FastReflectionFactories.PropertyAccessorFactory =new BetterPropertyAccessorFactory();        ...    }}
缓存的默认实现与扩展
  在FastReflectionLib中使用基于 System.Collections.Generic.Dictionary<TKey, TValue>类型编写的缓存容器。每次调用FastXxx扩展方法时,类库将从对应的缓存容器中获取工作对象。如果缓存容器中还没有所需的工作对象,那么它就会调用合适的Factory来构造新的工作对象。从下面的性能测试来看,许多时间是消耗在缓存查找上的,如果您有更好的缓存实现,可以使用以下的方法替换默认的缓存的容器:

public class BetterMethodInvokerCache :IFastReflectionCache<MethodInfo, IMethodInvoker>{public IMethodInvoker Get(MethodInfo key) { ... }}class Program{static void Main(string[] args)    {FastReflectionCaches.MethodInvokerCache = new BetterMethodInvokerCache();        ...    }}
根据需要自行缓存工作对象
  FastReflectionLib中通过PropertyInfo等对象作为Key,对PropertyAccessor等工作对象进行缓存。但是在某些场景下,您也可以选择合适的方式来自行缓存工作对象。与FastReflectionLib源码同时发布的CustomCache示例网站中包含了一个FastEval扩展,在某些场景下,我们可以使用这个更高效的方法来替换内置的Eval方法。这个示例的特点如下:

使用对象的类型和属性名同时作为缓存的Key获取对应的PropertyAccessor对象
使用PropertyAccessor获取“匿名对象”中的属性值
缓存的作用域为特定页面,而不是整个AppDomain。
性能测试
  FastReflectionLib源码中包含了一个性能测试项目,您可以从中看出FastReflectionLib对于反射的性能改进。摘录部分数据如下(测试在我的笔记本上运行,Release编译)。

  执行以下方法:

public class Test{public void MethodWithArgs(int a1, string a2) { }}
  进行一百万次调用,结果如下:

调用方式 消耗时间(秒)
方法直接调用 0.0071397
内置反射调用 1.4936181
工作对象调用 0.0468326
Fast方法调用 0.1373712

 

分享到:
评论

相关推荐

    libreflection2_src

    在C++编程语言中,反射(Reflection)是一种高级特性,允许程序在运行时检查自身,包括类、对象、函数等的属性和行为。这通常涉及动态类型检查、元编程和自省。`libreflection2_src`是一个开源项目,旨在提供一个...

    提升反射的性能(有用,启发)

    "Fast Reflection Library"可能介绍了一个专门设计用于提升反射性能的第三方库,该库通过预编译的委托或元数据缓存来减少运行时的开销,从而提高反射操作的速度。 "较为理想的延迟代理的编写方式"可能涉及延迟加载...

    CandyView-Library:仅需1行,即可在您的Andoird应用程序中实现任何RecyclerView。 CandyView Library使用Java中的Reflection为您处理一切

    在1行中实现RecyclerView的最简单方法。 美味的事实 :lollipop: 忘记为Adapters中的视图创建无味的Adapters和单调的findViewById 。 文本数据String, int, float ...... 图像URL String和图像可绘制(int) R.drawable....

    Android代码-Intimate

    Its core value is optimizing the reflection call at compile time, which completely save reflection search time,and make a reflection call as fast as a normal call. ' Intiamte only take action on the ...

    Android代码-kodable

    It's fast in runtime, very fast Compile time check for kodables - if there is no kodable for type we'll get exception while compilation no type erasure in runtime - all kodables called directly ...

    Clojure.High.Performance.JVM.Programming.epub

    Explore the world of lightning fast Clojure apps with asynchronous channels, logic, reactive programming, and more About This Book Discover Clojure's features and advantages and use them in your ...

    Novus:用于CLR和内存的低级实用程序和工具

    Novus旨在提供与ClrMD , WinDbg SOS和Reflection相似的功能,但以更详细的方式提供,同时还公开了更多基础元数据和CLR功能。 Novus还允许使用受管理对象来操纵CLR和低级操作。 此外, Novus不需要将调试器附加到...

    RazorSharp:用于CLR和内存的低级实用程序和工具

    目标RazorSharp旨在提供与ClrMD , WinDbg SOS和Reflection相似的功能,但以更详细的方式提供,同时还公开了更多基础元数据和CLR功能。 RazorSharp还允许操纵CLR和使用托管对象进行低级操作。 此外, RazorSharp不...

    XSeries:跨版本Minecraft Bukkit支持和各种有效API方法的库

    X系列 该库主要旨在为Minecraft Bukkit服务器提供跨版本支持,但它还包括许多其他方法,可帮助开发人员更轻松,更高效地设计其插件。 一些实用程序与跨版本支持完全无关,例如NoteBlockMusic。...

    Professional C# 3rd Edition

    Fast Data Access: The Data Reader 701 Managing Data and Relationships: The DataSet Class 704 Data Tables 704 Data Columns 705 Data Relationships 711 Data Constraints 713 XML Schemas 715 Generating ...

Global site tag (gtag.js) - Google Analytics