为什么反射在.NET中表现不好?

为什么反射在.NET中表现不好?,.net,performance,reflection,.net,Performance,Reflection,我很想知道技术原因:为什么反射在.NET中表现不好?因为它涉及到运行时的字符串查找(类型和成员名称),以及值类型的额外装箱/取消装箱。MSDN上关于这方面的精彩文章:。基本上,这是一个后期和早期绑定的问题。也就是说,什么可以在编译时决定,什么必须在运行时决定。从那篇文章 迟交案件是 MethodBase.Invoke,DynamicMethod通过 Invoke、Type.InvokeMember和 延迟绑定的委托调用(在 通过Delegate.DynamicInvoke)委派。 所有这些方法都

我很想知道技术原因:为什么反射在.NET中表现不好?

因为它涉及到运行时的字符串查找(类型和成员名称),以及值类型的额外装箱/取消装箱。

MSDN上关于这方面的精彩文章:。基本上,这是一个后期和早期绑定的问题。也就是说,什么可以在编译时决定,什么必须在运行时决定。从那篇文章

迟交案件是 MethodBase.Invoke,DynamicMethod通过 Invoke、Type.InvokeMember和 延迟绑定的委托调用(在 通过Delegate.DynamicInvoke)委派。 所有这些方法都是随附的 明显更消极 性能影响比 早期绑定案例。即使是最好的 在这种情况下,它们通常是 震级比最慢的慢 早期绑定案例


他打破了我们对各种早晚通话方式的不少性能测试。值得一读。

反射涉及到将名称解析为标记的元数据,然后使用该标记查找和检索所需的数据(例如,使用方法标记获取有关方法、参数等的信息)

由于两个原因,此过程成本高昂。 1-正在进行大量查找。 2-触摸通常不被触摸的页面(冷页面),其中包含元数据表

直接访问元数据的成本很高,CLR维护缓存以加快此过程,并避免在以非反射方式访问内容时触碰元数据表,但是一旦转到反射,我们将绕过这些缓存直接转到源

反射效果不好

这是一个很有分量的陈述。“表现良好”是相对的。与静态代码相比,反射调用的性能不太好。然而,在几乎所有情况下,.NET中的反射速度都非常快。我不能低估这一点。反射在.NET1.x和其他语言中名声不好,但是.NET2.0+中的反射速度非常快


在99%的案例中,“反思是否太慢”是一个无关紧要的问题。我怀疑您是否需要费心衡量反射调用与静态调用对性能的影响。

反射在.NET中的性能确实很好,因为它确实如此

然而,由于反射是对已编译类型的运行时分析,因此需要相当大的开销。一般来说,执行静态类型信息的字符串查找、遍历类元数据等操作需要一段时间

这并不是说它真的很慢——它只是比完全编译的strait方法调用和查找慢得多。应该是这样的,但我认为,在任何系统中,编译后的代码都比动态查找信息快。

简单地说“反射”执行速度慢,就是将大量功能混为一谈。NET中的反射分为几个类,每个类都有不同的“性能”级别。首先,使用
typeof()
操作符实际上是一种反射形式……它查询CLR元数据中的类型。但是,
typeof()
执行速度非常快(在几乎空闲的时间内)。使用其他类型相关的“反射”,例如is操作符、
sizeof()
操作符等,也几乎是免费的(它们的执行基本上就像是静态代码一样)

用于检索类型信息的反射虽然比
typeof()
慢,但考虑到指针遍历和元数据探测的数量,反射也非常非常快。元数据探测是.NET代码中相当常见的做法,尤其是在使用自定义属性时

关于反射的最大性能问题与调用有关。访问类型信息和读取元数据的重量非常轻。当您涉及到属性、索引器、方法的动态调用,或者通过反射动态构造新类型时,您的性能会受到几个数量级的影响

但是,反射仍然是进程内执行,因此在您担心一点动态调用对性能的影响之前,请确保在性能方面没有任何明显更大的性能瓶颈,例如进程间执行、网络调用(即数据库、web服务等),从最大的性能冲击开始,然后从那里开始工作。从性能的角度来看,反射(包括动态调用)通常是您最不应该担心的事情之一

附录:


有点事后诸葛亮,但如果您需要后期绑定类型成员的高度动态调用,则应该研究轻量级代码生成。使用System.Reflection.Emit命名空间,您可以使用DynamicMethod等实用程序在运行时生成可执行早期绑定调用的轻量级代码。缓存生成的代码可以降低生成代码的初始成本,使您能够利用早期绑定性能获得后期绑定调用的好处。

反射性能很好,它比静态代码做得更多

假设您有以下代码段:

typeof(SomeClass).GetMethod("SomeStaticMethod").
Invoke(null, new object[] { 1, 2, 3 });
这与此相同:

SomeClass.SomeStaticMethod(1, 2, 3);
但很明显,第一个问题还有很多工作要做。它必须获取类型信息,遍历它以查看是否有SomeStaticMethod方法,检查它是什么类型的方法,在实例上调用该方法,或者如果它是静态的,则不调用该方法,并传递对象数组is参数,在这种情况下也装箱/取消装箱整数

这可能是一个非常广泛的总结,毫无疑问,还有更多的内容。然而,尽管如此,反射仍然非常快,并在很多领域得到了应用,从WinForms上的数据绑定到ASP.NET MVC中的模型绑定(您发出的每个请求)