.NETreflection代价如何?

我经常听到reflection是多么糟糕。 虽然我通常避免反思,很less发现没有它的情况下不可能解决我的问题,但我想知道…

对于那些在应用程序中使用过reflection的人来说,你是否测量了性能点击,是不是真的很糟糕?

它是。 但这取决于你想要做什么。

我使用reflectiondynamic加载程序集(插件),它的性能“惩罚”不是一个问题,因为操作是我在应用程序启动过程中所做的。

但是,如果你在每个reflection调用里面reflection一系列嵌套循环,我会说你应该重新访问你的代码:)

对于“几次”操作,反思是完全可以接受的,你不会注意到任何延迟或问题。 这是一个非常强大的机制,它甚至被.NET使用,所以我不明白为什么你不应该试一试。

Jeff Richter在他的演讲“日常事物的performance”中表明,通过反思调用一种方法比正常调用慢1000倍

杰夫的提示:如果您需要多次调用该方法,请使用reflection一次来find它,然后将其分配给委托 ,然后调用委托。

reflection性能将取决于实现(重复调用应caching,例如: entity.GetType().GetProperty("PropName") )。 由于我每天都会看到大多数reflection用于从数据读取器或其他存储库types结构中填充实体,所以我决定在用于获取或设置对象属性时专门针对reflection进行性能基准testing。

我devise了一个我认为公平的testing,因为它caching了所有的重复调用,只调用实际的SetValue或GetValue。 性能testing的所有源代码位于: https ://bitbucket.org/grenade/accessortest。 审查受到欢迎和鼓励。

我得出的结论是,这是不实际的,并没有提供显着的性能改进,以消除reflection实施完成时一次返回less于100,000行的数据访问层中的reflection。

时间(y)与实体数量(x)的关系图

上面的图表显示了我的小基准的输出,并且显示了超过reflection的机制,仅在100,000个周期标记之后才显着。 大多数DALs一次只能返回数百或者甚至数千行,并且在这些级别上reflection性能很好。

我最相关的经验是编写代码来比较大型对象模型中的任何两个相同types的数据实体。 得到它的工作,试了一下,很明显,像一条狗跑。

我沮丧,然后一夜之间意识到,不改变逻辑,我可以使用相同的algorithm自动生成方法进行比较,但静态访问的属性。 为了达到这个目的,我们没有花时间去修改代码,而且我有能力对静态代码进行深度的属性比较,只要对象模型发生变化,只要点击一下button就可以更新这些代码。

我的观点是:在与同事的对话中,我曾多次指出,他们使用reflection可能会自动生成代码来编译而不是执行运行时操作,这经常值得考虑。

如果你不在环路中,不要担心。

不是大规模的。 我从来没有在桌面开发方面遇到过问题,除非像马丁所说的那样,你在一个愚蠢的地方使用它。 我听说很多人对桌面开发的performance完全没有理由担心。

在精简版框架 (我通常是这样)中,它几乎是一个networking,应该像大多数情况下的瘟疫一样避免。 我仍然可以不经常使用它,但是我必须非常小心它的应用程序,而不是那么有趣。 🙁

这足够糟糕,甚至不得不担心.NET库对于性能关键代码的内部reflection。

以下示例已过时 – 在当时(2008年)是正确的,但在较早的CLR版本中很久以前就已修复。 尽pipe如此,反思总体来说还是有点贵的。

例如:在高性能代码中,不应使用在锁(C#)/ SyncLock(VB.NET)语句中声明为“Object”的成员。 为什么? 由于CLR无法locking值types,这意味着它必须执行运行时reflectiontypes检查,以查看您的对象是否实际上是值types而不是引用types。

和编程中的所有事情一样,你必须平衡性能成本和获得的任何好处。 reflection是一个宝贵的工具时小心使用。 我在C#中创build了一个使用reflection来完成绑定的O / R映射库。 这工作非常好。 大多数的reflection代码只执行一次,所以任何性能的打击都是相当小的,但好处是巨大的。 如果我正在写一个新的sortingalgorithm,我可能不会使用reflection,因为它可能会缩小比例。

我明白,我并没有完全在这里回答你的问题。 我的观点是,这并不重要。 适当时使用reflection。 这只是另一种语言function,您需要了解如何以及何时使用。

如果将其用于频繁创build对象,reflection会对性能产生显着影响。 我已经开发了基于综合UI应用程序块的应用程序 ,它依赖于大量的reflection。 与通过reflection创build对象相关的性能下降明显。

但是在大多数情况下,reflection使用没有问题。 如果你只需要检查一些assembly,我会推荐Mono.Cecil ,它非常轻巧,快速

reflection是昂贵的,因为每当你请求一个匹配参数列表的方法时,运行时必须进行许多检查。 在内部的某个地方,代码存在循环遍历types的所有方法,validation其可见性,检查返回types,并检查每个参数的types。 所有这些东西都花费时间。

当你在内部执行这个方法时,会执行一些代码,比如检查你在执行实际的目标方法之前传递了一个兼容的参数列表。

如果可能的话,总是build议一个caching方法句柄,如果将来不断重用的话。 像所有好的编程技巧一样,避免重复自己常常是有道理的。 在这种情况下,不断地用特定的参数查找方法,然后每次都执行它是很浪费的。

打开源文件,看看正在做什么。

就像所有事情一样,都是关于评估情况。 在DotNetNuke中有一个相当核心的组件FillObject ,它使用reflection来填充数据行中的对象。

这是一个相当常见的情况,MSDN上有一篇文章, 使用reflection将业务对象绑定到ASP.NET表单控件 ,覆盖了性能问题。

除了性能之外,我不喜欢在特定情况下使用reflection的一点是,它往往会降低快速了解代码的能力,对于我来说,如果您认为自己也会失去编译的function时间安全性,而不是强types数据集或类似LINQ to SQL 。

reflection并不会显着减慢应用程序的性能。 您可以通过不使用reflection来更快地完成某些操作,但如果Reflection是实现某些function的最简单方法,那么可以使用它。 如果它成为一个性能问题,你总是可以重构你的代码。

我想你会发现答案是,这取决于。 如果你想把它放在你的任务列表应用程序中,这不是什么大不了的事情。 如果你想把它放在Facebook的持久性库中,这是一个大问题。