2014-10-09 86 views
4

我一直在阅读虚拟方法以及它们是如何被调用的。正如所讨论的herehere,我已经得出结论,他们不应该真的如此不同。虚拟方法比非虚拟方法要慢

C#编译器发出IL代码,该代码通过call IL指令调用静态方法,并通过callvirt调用虚拟/非虚拟成员。看起来JIT的工作实际上是确定被调用的方法对象是否实际为空。所以这两项检查都是一样的。另外,正如在第一篇文章中讨论的那样,在编译时,看起来vtables或者表格保存着方法定义的元数据,在编译时被展平了。换句话说,这些表确切地包含了对象应该调用的方法,而不需要对继承链进行递归搜索。

综上所述,为什么虚拟方法被认为比较慢?也许是一个间接的(如果有的话)那么大的一笔交易?请解释...

+0

* CLR只通过调用IL指令调用静态方法*是有误导性的。它是C#编译器,它为静态和'callvirt'发出'call'指令作为实例方法。其他编译器可以自己的方式自由地实现它。 CLR与此无关。 – 2014-10-09 15:14:38

+0

@SriramSakthivel真。我会换个话。 – 2014-10-09 15:15:52

+0

相关:http://stackoverflow.com/questions/530799/what-are-the-performance-implications-of-marking-methods-properties-as-virtual – 2014-10-09 15:28:53

回答

1

您正在研究函数调用指令与直接与间接寻址之间的区别。但是间接函数调用的大部分“成本”不是调用本身,而是失去了执行需要对目标进行静态知识的优化的机会。内联,跨程序混叠分析等等。

1

找出要执行哪个实际方法实施将具有的一些成本,而不仅仅是知道。该成本可能非常小,并且很可能成本对于任何特定背景都是完全可以忽略的,因为它确实不需要很长的时间。但成本是非零的,所以在特别对性能敏感的应用中,它会使的一些的差异。

+0

寻找实际的实施是反对的声明,虚拟桌面被夷为平地编译时间。那么你是否相信CLR仍然需要遵循继承链?如果不是,并且如果您在对象所引用的“类型对象”的元数据中评论实际的“方法表”,对于非虚拟方法,这不是相同的情况吗?换句话说,在编译时对于任何给定类型的方法表槽中记录的右偏移量是否不是平坦的? – 2014-10-09 15:22:15

+0

@FarhadAliNoo如果方法是虚拟的,则需要检查对象的实际运行时类型,并且需要在vtable中查找该类型的给定方法的实现。对于非虚拟方法,这些都不需要发生;该方法在编译时绑定。 – Servy 2014-10-09 15:26:17