【发布时间】:2017-08-02 06:09:01
【问题描述】:
使用 C#,但我认为这个问题也与其他(大多数与 c 相关的)语言有关。 考虑一下...
private float radius = 0.0f; // Set somewhere else
public float GetDiameter() {
return radius * 2.0f;
}
如果在其他类中调用,编译器会内联吗?我认为答案当然是,但这里有一些困惑:radius 是私有的。所以从手动编程的角度来看,我们不可能内联这个方法,因为 radius 是私有的。
那么编译器做了什么?我认为它无论如何都可以内联它,因为如果我没记错的话,“私人”“公共”等。修饰符只影响人类编写的代码,而汇编语言可以根据需要访问自己程序的任何部分?
好的,但是抽象呢? 考虑一下...
public abstract class Animal {
abstract public bool CanFly();
}
public class Hawk : Animal {
...
override public bool CanFly() {
if (age < 1.0f) return false; // Baby hawks can't fly yet
return true;
}
}
public class Dog : Animal {
...
override public bool CanFly() {
return false;
}
}
在非动物类中:
...
Animal a = GetNextAnimal();
if (a.CanFly()) {
...
这可以内联吗?我几乎可以肯定不会,因为编译器不知道正在使用哪种动物。但如果我这样做了……
...
Animal a = new Hawk();
if (a.CanFly()) {
...
这有什么不同吗?如果没有,这个肯定可以吗?:
...
Hawk a = new Hawk();
if (a.CanFly()) {
...
如果我不使用上面的 bool 方法,有什么改变吗:
float animalAge = a.GetAge();
一般来说,过多的抽象 getter 和 setter 会导致性能下降吗?如果这达到了重要的程度,那么最好的解决方案是什么?
【问题讨论】:
-
我认为在 C# 世界(以及许多其他基于 VM 的语言)中,这变得更加复杂,因为有一个从 C# 到 IL 的编译器可以进行一些优化,包括内联并且有一个 VM JIT 编译器也进行了一些优化,包括内联,但 JIT 编译器也可能依赖于一些统计指标,例如注意到
GetNextAnimal总是以某种方式生成Hawk并因此将 'Hawk' 的代码与一个小的 pre-检查/捕获此条件是否成立(如果不生成更多/不同的代码) -
观看 YouTube 上的 "When Does the JVM JIT & Deoptimize?" 视频 这是针对 Java 的,但 C# 类似。它展示了许多惊人的技巧,但当他描述“推测优化”时,一些与您的问题最相关的技巧会在 1:00 - 1:15 左右显示。还可以查看slideshare.net/dougqh/jvm-mechanics-when-does-the 上同一演示文稿的幻灯片 #89,其中显示了一些相关的 JVM 配置,例如
MaxInlineLevel另见 Inline caching Wiki 上的文章
标签: performance compilation inline private abstract