.NET反射的代价是多少?

时间:2008-08-24 23:40:17

标签: c# .net performance reflection

我经常听到反射的糟糕程度。虽然我一般都避免反思,很少发现没有它就无法解决问题的情况,我想知道......

对于那些在应用程序中使用过反射的人,您是否测量过性能命中率,是否真的如此糟糕?

13 个答案:

答案 0 :(得分:147)

在他的演讲The Performance of Everyday Things中,杰夫里希特表示,通过反思调用方法比正常调用<强> 1000倍。

Jeff的提示:如果您需要多次调用该方法,请使用一次反射来查找它,然后将其分配给委托,然后调用该委托。

答案 1 :(得分:125)

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

我使用反射来动态加载程序集(插件),并且它的性能“惩罚”不是问题,因为操作是我在应用程序启动期间所做的事情。

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

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

答案 2 :(得分:57)

反射性能取决于实现(重复调用应该缓存,例如:entity.GetType().GetProperty("PropName"))。由于我日常看到的大多数反射用于从数据读取器或其他存储库类型结构中填充实体,因此我决定在用于获取或设置对象属性时专门针对反射进行性能测试。

我设计了一个我认为合理的测试,因为它缓存了所有重复调用,并且只调用了实际的SetValue或GetValue调用。性能测试的所有源代码都在bitbucket:https://bitbucket.org/grenade/accessortest。欢迎并鼓励审查。

我得出的结论是,它不实用,并且没有提供明显的性能改进,以消除数据访问层中的反射,该反射实现完成后,返回少于100,000行。

Graph of time (y) against number of entities populated(x)

上图显示了我的小基准测试的输出,并显示出优于反射的机制,仅在100,000次循环标记后才显着。大多数DAL一次只返回几百行或几千行,在这些级别上,反射表现得很好。

答案 3 :(得分:14)

如果您不在循环中,请不要担心。

答案 4 :(得分:12)

我最相关的经验是编写代码以在属性方面比较大对象模型中相同类型的任何两个数据实体。得到它的工作,尝试它,显然像狗一样跑。

我很沮丧,然后一夜之间意识到无论改变逻辑,我都可以使用相同的算法来自动生成进行比较但静态访问属性的方法。我们花了很长时间才为此目的调整代码,并且我有能力对实体进行深度属性比较,静态代码可以在对象模型发生变化时通过单击按钮进行更新。

我的观点是:在与同事的对话中,因为我曾多次指出他们使用反射可以自动生成代码进行编译而不是执行运行时操作,这通常值得考虑。

答案 5 :(得分:12)

不大规模。我在桌面开发中从来没有遇到过这个问题,除非像Martin说的那样,你在一个愚蠢的位置使用它。我听说很多人对其在桌面开发中的表现完全没有理性的恐惧。

Compact Framework(我通常在其中),它几乎是anathema,在大多数情况下应该像瘟疫一样避免。我仍然可以不经常使用它,但我必须非常小心它的应用程序,这是不那么有趣。 :(

答案 6 :(得分:10)

对于性能关键代码,你必须担心.NET库内部完成的反射是非常糟糕的。

以下示例已过时 - 当时为真(2008),但很久以前修复了更新的CLR版本。尽管如此,反思总的来说仍然是一件昂贵的事情!

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

答案 7 :(得分:5)

与编程中的所有内容一样,您必须平衡性能成本与获得的任何好处。在小心使用时,反思是一种非常宝贵的工具。我在C#中创建了一个O / R映射库,它使用反射来进行绑定。这非常有效。大多数反射代码只执行一次,所以任何性能影响都很小,但好处很大。如果我正在编写一个新的fandangled排序算法,我可能不会使用反射,因为它可能会扩展得很差。

我感谢我在这里没有完全回答你的问题。我的观点是,它并不重要。适当时使用反射。这只是您需要了解如何以及何时使用的另一种语言功能。

答案 8 :(得分:3)

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

这是一个相当常见的情况,有一篇关于MSDN的文章, Using Reflection to Bind Business Objects to ASP.NET Form Controls ,它涵盖了性能问题。

除了性能之外,我不喜欢在特定情况下使用反射的一件事是,它倾向于在快速浏览时降低了理解代码的能力,这对我来说当你考虑到你时似乎不值得付出努力与强类型数据集或类似LINQ to SQL之类的东西相比,也会失去编译时安全性。

答案 9 :(得分:3)

如果您使用反射创建频繁的对象,则反射会对性能产生显着影响。我开发了基于Composite UI Application Block的应用程序,它依赖于反射。通过反射创建对象时,性能明显下降。

但是在大​​多数情况下,反射使用没有问题。如果你唯一的需要是检查一些程序集,我会建议Mono.Cecil非常lightweight and fast

答案 10 :(得分:3)

由于每当您请求与参数列表匹配的方法时,运行时必须进行许多检查,因此反射成本很高。在内部深处,代码存在循环遍历类型的所有方法,验证其可见性,检查返回类型以及还检查每个参数的类型。所有这些都需要时间。

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

如果可能的话,总是建议一个缓存方法句柄,如果将来要继续重用它。像所有好的编程技巧一样,避免重复自己通常是有意义的。在这种情况下,使用某些参数不断查找方法然后每次都执行它将是浪费。

在源头周围逛逛,看看目前的情况。

答案 11 :(得分:2)

反射不会大幅降低应用的效果。您可以通过不使用反射来更快地执行某些操作,但如果Reflection是实现某些功能的最简单方法,那么请使用它。如果它成为一个性能问题,你总是可以从反射中重构代码。

答案 12 :(得分:1)

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