.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。
上面的图表显示了我的小基准的输出,并且显示了超过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的持久性库中,这是一个大问题。