C# 虚拟成员可以内联吗?

问题描述 投票:0回答:2

考虑以下派生内部类旨在重写的替代实现,返回

true

public virtual bool IsInternal => false;

...还有...

public virtual bool IsInternal() => false;

内存和性能方面有什么区别?

编译器是否可以检测静态结果,并在优化/内联时使用它们,而不是保存每个实例的属性值或调用函数? 这些虚拟成员是否可以被编译器内联,会产生什么影响?

c# performance compiler-optimization
2个回答
4
投票

内存和性能方面有什么区别?

无,它们都编译为虚拟方法(C# 属性只是 getter+setter 方法的不同语法)。

每个虚拟成员都会增加类型的

vtable
大小(但这可以忽略不计,因为 vtable 是按类型而不是按实例)。

从性能角度来看,虚拟调用会花费一些更昂贵的指令,并且还需要更多的内存访问,但良好的 CPU、现代分支预测和大型缓存可以最大限度地减少影响。如果您真的关心该级别的性能,那么您无论如何都不会使用 CLR - 就大多数开发人员而言应该关心的是

virtual
调用成本与非虚拟调用相同。

编译器是否可以检测静态结果,并在优化/内联时使用它们,而不是保存每个实例的属性值或调用函数?

  • .NET Framework 1.0、1.1、2.0 和 4.0 中的 CLR 没有(据我所知)。在某些微不足道的情况下(例如 (new BaseVirtualType().VirtualMethod())),C# 编译器

    可能会在编译的 CIL 中用非虚拟调用替换虚拟调用,但 JIT 不会进行这种优化(但 JIT 
    可能会内联它,但我不确定)。当启用优化时,C# 编译器也可能内联。

  • 根据 .NET Core 3.0 的规范文档(见下文),.NET Core 2.0 中的 CLR 进行了

    some去虚拟化。

  • .NET Core 3.0 中的 CLR 将更加激进,这是继承者规范文档:

    https://github.com/dotnet/coreclr/blob/master/Documentation/design-docs/GuardedDevirtualization.md


0
投票

更新

请参阅 JIT 部分,了解从 .NET 6 开始可用的改进:

https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/#jit

...JIT 进行虚拟或接口方法调用,确定 静态地调用的实际最终目标,并发出直接 调用该目标,节省虚拟调度的成本。一次 去虚拟化后,目标也可能被内联。

另请参阅 密封类真的能提供性能优势吗? 和

https://stackoverflow.com/a/53785972/19497610

© www.soinside.com 2019 - 2024. All rights reserved.