.NET反射的代价是多少?

Dan*_*ert 204 .net c# reflection performance

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

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

ESR*_*ogs 149

在他的演讲"日常生活中的表现"中,杰夫里希特表明,通过反射调用方法比正常调用方法大约1000倍.

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

  • 我也参加了Devscovery,并同意.NET 3.5的这些结果.重新编译.NET 4的Devscovery性能基准程序显示了巨大的改进!成本下降到100倍慢.在.NET 3.5和.NET 4之间使用反射进行typeof()查找不变. (17认同)

Mar*_*ini 128

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

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

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

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

  • @Sangram虽然反射性能不应该是你的情况下的问题,看起来你似乎正在尝试重新实现普通的旧异常以更优雅的方式开箱即用... (5认同)

gre*_*ade 59

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

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

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

时间(y)与填充实体数量的图表(x)

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

  • 不必要.您的DAL转换可能只有几千个项目,但是使用您的应用程序的并发用户(如果它是Web)会增加,并且它可能会加起来就像您转换了百万项目一样.如果特定方法的速度慢100倍,那么在小型和大型集合上会慢得多.慢得慢. (9认同)
  • 图表上的Hyper方法是什么?它与Reflector有什么不同? (2认同)

Dav*_*ton 14

如果你不在循环中,不要担心它.


Gaz*_*Gaz 12

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

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

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


Qui*_*ome 12

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

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

  • +1教我一个新词:anathema.还提到了非理性的恐惧.我担心那些害怕非理性的程序员 - 这表明他们并不真正知道他们在做什么,只是把他们所做的事基于其他人告诉他们的事情.*咳嗽货物邪教咳嗽* (5认同)
  • 啊啊货物崇拜。现在有一个很好的例子来说明人类的好奇行为。 (2认同)

McK*_*eG1 10

对于性能关键代码,你必须担心.NET库内部完成的反射,这已经够糟糕了.

以下示例已过时 - 当时为真(2008),但很久以前修复了更新的CLR版本.但总的来说反思仍然是一件有点代价的事情!

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

  • 公平地说,反射型检查很快. (13认同)

Mik*_*son 5

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

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