我经常听说使用反射是多么糟糕。虽然我通常避免反思,也很少发现不反思就无法解决问题的情况,但我在想……
对于那些在应用程序中使用反射的人,您测量过性能影响吗?它真的那么糟糕吗?
我经常听说使用反射是多么糟糕。虽然我通常避免反思,也很少发现不反思就无法解决问题的情况,但我在想……
对于那些在应用程序中使用反射的人,您测量过性能影响吗?它真的那么糟糕吗?
它是。但这取决于你要做什么。
我使用反射动态加载程序集(插件),它的性能“惩罚”不是问题,因为操作是我在应用程序启动期间所做的事情。
然而,如果你在一系列嵌套循环中反射,每个循环都有反射调用,我想说你应该重新审视你的代码:)
对于“几次”操作,反射是完全可以接受的,您不会注意到任何延迟或问题。它是一种非常强大的机制,甚至被。net使用,所以我不明白为什么你不应该尝试一下。
和所有事情一样,这都是关于评估形势。在DotNetNuke中,有一个相当核心的组件叫做FillObject,它使用反射从数据箭头填充对象。
这是一个相当常见的场景,在MSDN上有一篇文章,使用反射将业务对象绑定到ASP。NET表单控件,涵盖了性能问题。
除了性能之外,我不喜欢在这种特定情况下使用反射的一件事是,它往往会降低快速理解代码的能力,对我来说,当你考虑到与强类型数据集或类似LINQ to SQL的数据集相比,你还失去了编译时的安全性,这似乎不值得付出努力。
如果将反射用于频繁创建对象,则它会对性能产生显著影响。我开发了一个基于复合UI应用程序块的应用程序,它严重依赖反射。通过反射创建对象时,有明显的性能下降。
但是在大多数情况下,使用反射是没有问题的。如果你只需要检查一些组装,我会推荐Mono。塞西尔,非常轻,速度很快
As with all things in programming you have to balance performance cost with with any benefit gained. Reflection is an invaluable tool when used with care. I created a O/R mapping library in C# which used reflection to do the bindings. This worked fantastically well. Most of the reflection code was only executed once, so any performance hit was quite small, but the benefits were great. If I were writing a new fandangled sorting algorithm, I would probably not use reflection, since it would probably scale poorly.
很抱歉,我还没有完全回答你的问题。我的观点是,这并不重要。在适当的地方使用反射。它只是你需要学习如何以及何时使用的另一种语言功能。
在Jeff Richter的演讲The Performance of Everyday Things中,他展示了通过反射调用一个方法要比正常调用慢1000倍。
Jeff的建议:如果需要多次调用该方法,请使用一次反射来找到它,然后将其分配给委托,然后调用委托。
您甚至不得不担心. net库内部为性能关键型代码所做的反射,这已经够糟糕的了。
下面的例子在当时(2008年)是过时的,但在最近的CLR版本中早就修复了。不过,总的来说,反思仍然是一件有点昂贵的事情!
举个例子:在高性能代码中,永远不要在lock (c#) / SyncLock (VB.NET)语句中使用声明为“Object”的成员。为什么?因为CLR不能锁定值类型,这意味着它必须执行运行时反射类型检查,以查看您的对象是否实际上是值类型而不是引用类型。
我最相关的经验是编写代码来比较大型对象模型中相同类型的任何两个数据实体的属性。把它修好,试了试,显然跑得像条狗。
我很沮丧,然后在一夜之间意识到,在不改变逻辑的情况下,我可以使用相同的算法自动生成方法来进行比较,但静态地访问属性。为了这个目的调整代码完全不花时间,而且我有能力对实体与静态代码进行深入的属性比较,每当对象模型发生变化时,只要单击按钮就可以更新静态代码。
我的观点是:在与同事的对话中,因为我已经多次指出他们使用反射可以自动生成代码来编译,而不是执行运行时操作,这通常值得考虑。
不严重。我从来没有在桌面开发中遇到过问题,除非,正如Martin所说,你在一个愚蠢的位置使用它。我听说很多人对它在桌面开发中的表现有完全不合理的担忧。
然而,在紧凑框架(我经常参与)中,它几乎是一种诅咒,在大多数情况下应该像瘟疫一样避免。我仍然可以不经常使用它,但我必须非常小心地使用它,这就不那么有趣了。:(
反射不会大幅降低应用程序的性能。不使用反射可能会更快地完成某些事情,但如果反射是实现某些功能的最简单方法,那么就使用它。如果反射成为一个性能问题,你总是可以重构你的代码。
反射的代价很高,因为每当您请求与参数列表匹配的方法时,运行时必须进行许多检查。在内部的某个深处,存在一些代码,它们循环遍历一个类型的所有方法,验证其可见性,检查返回类型,并检查每个参数的类型。所有这些都需要时间。
当你在内部执行这个方法时,有一些代码会在执行实际的目标方法之前检查你传递了一个兼容的参数列表。
如果可能,总是建议缓存方法句柄,如果将来要不断地重用它。像所有好的编程技巧一样,避免重复通常是有意义的。在这种情况下,不断地查找具有特定参数的方法,然后每次都执行它将是一种浪费。
戳一下源代码,看看正在做什么。
反射性能将取决于实现(重复调用应该被缓存,例如:entity.GetType(). getproperty ("PropName"))。由于我每天看到的大多数反射都用于从数据阅读器或其他存储库类型结构填充实体,所以我决定在反射用于获取或设置对象属性时对其性能进行基准测试。
我设计了一个测试,我认为是公平的,因为它缓存所有重复的调用,只乘以实际的SetValue或GetValue调用。性能测试的所有源代码都在bitbucket中:https://bitbucket.org/grenade/accessortest。审查是受欢迎和鼓励的。
我得出的结论是,在反射实现做得很好的情况下,在数据访问层中删除反射是不实际的,也不能提供明显的性能改进。
上图展示了我的小基准测试的输出,并显示了优于反射的机制,只有在100,000次循环之后才会明显表现出来。大多数dal一次只返回几百行或数千行,在这些级别反射执行得很好。