反思真的很慢吗?
这是一种普遍的看法,即反思很慢,并试图尽可能地避免它。 但在目前的情况下,这种信念是否属实? 目前的.net版本有很多变化,比如使用IL Weaving(即IL Emit)等,而不是传统的PropertyInfo和MethodInfo进行reflection的方式。
这是否有任何令人信服的证据,新的反映不再那么慢,而且可以使用。 是否有更好的方法来读取属性数据?
谢谢,巴斯卡尔
当你想到它时,reflection速度相当快,令人印象深刻。
可以使用与任何其他委托相当的速度调用ConstructorInfo
或MethodInfo
高速缓存委托。
从ILGenerator.Emit
创建的委托(顺便说一下,它不是新的,从版本1开始就在.NET中)也可以同样快速地调用。
通过发出或调用ConstructorInfo
的委托获得的对象将与任何其他对象一样快。
如果您通过动态加载程序集来获取对象,使用reflection来查找要调用的方法并调用它,并且它实现了一个已定义的接口,您可以通过该接口从该点开始调用它,那么它将如何快速地它被用作该接口的另一个实现。
总而言之,reflection为我们提供了做事的方法,没有它我们会 – 如果我们可以完成它们 – 必须使用速度慢的代码和执行技术。
它还为我们提供了比其他方法更复杂,更脆弱,更少类型安全且性能更低的方法。 几乎每一行C#代码都可以被一大堆使用reflection的代码所取代。 在很多方面,这段代码几乎肯定会比原始代码更差,性能最差。
很可能“避免反思,因为它的缓慢”建议源于这样的信念:那种开发人员会为任何新技术而疯狂只是因为它看起来很酷将更有可能被“它将被警告”慢“而不是”它会更少惯用,更容易出错并且难以维持“。 很可能这种信念是完全正确的。
但是,在大多数情况下,当最自然和最明显的方法是使用reflection时,它的性能也不会低于真正错综复杂的避免它的尝试。
如果性能问题适用于reflection中的任何内容,那么它实际上是隐藏的用途:
在只有少量工作可以避免它的情况下,使用dynamic
似乎是明智的。 这里的性能差异可能值得考虑。
在ASP.NET中,使用<%#DataBinder.Eval(Container.DataItem, "SomeProperty")%>
比<#((SomeType)Container.DataItem).SomeProperty%>
更容易,但通常性能<#((SomeType)Container.DataItem).SomeProperty%>
或<%#SomeCodeBehindProvidedCallWithTheSameResult%>
。 我仍然会在前90%的时间使用前者,而后者只有在我真正关心给定页面的性能时才会使用,或者更可能因为对同一对象进行多次操作会使后者更自然。
总而言之,计算机中的一切仍然“缓慢”,而它们受限于需要以消耗能量并花费时间的方式在单个宇宙中工作,对于某些“慢”的值。 不同的reflection技术有不同的成本,但替代方案也是如此。 在那些作为隐藏reflection的明显方法的情况下要注意的不是reflection,而另一种方法稍微不那么明显可能很好。
当然,使用您使用的任何技术明智地编码。 如果你要连续一百次调用同一个委托,那么你应该存储它而不是每次调用都能获得它,那么获取它的方式是否通过reflection来实现。
这完全取决于。
是的,使用reflection毫无疑问比不使用reflection慢,但你必须看一下大局:
例如,假设您的代码进行了一些reflection,然后通过网络从数据库加载一些数据。
在这种情况下,您可以完全忽略reflection的额外成本,因为通过网络的数据库请求可能需要更长时间。
我不会担心性能成本太高。 并不是说性能无关紧要,但在很多情况下,毫秒或两秒都不明显,或者值得选择更复杂的编码方案。 看看这里 。
我通常更喜欢这种方法:
- 写简单的代码
- 衡量绩效
- 如果需要,优化最大的击球手
你的意思是提到一个共同的信念吗? 反思不是一个坚实的障碍。 你应该考虑每种方法。 例如,通过默认构造函数创建对象比简单调用慢几倍,而创建参数化构造函数则慢十几倍。 因此,如果您想研究速度,请执行基准测试并对您需要的具体function进行基准测试。
PS。 使用C#,您可以随时创建和编译表达式 ,如果您设法执行它将比reflection快得多。
当我们尝试在庞大的操作或循环中进行时,reflection很慢。 你也可以尝试动态选项。 使用动态选项,它可以被缓存,最终将比reflection更快。
如果您需要查看应用于源代码的属性,那么您几乎必须使用reflection。
一些reflection操作很快,例如Object.GetType(),但是一些操作相对较慢,例如Type.FindMethod(“MyMethod”)。
一般来说,我会说,如果您的应用程序偶尔使用Reflection,那么应该没有性能问题。 另一方面,如果您的应用程序广泛使用Reflection,那么您可能会观察到一些缓慢。
内省是一项繁重的工作。 说慢是相对于很多事情。 通过reflection调用方法/构造函数很慢,但是使用reflection只能检索metadatas。
请记住,reflection必须仅用于检索元数据。 如果需要调用方法,运行某些东西,只需在初始化时发出动态类型/方法,并通过接口/委托调用它们。