是否会在编译时优化局部变量的一次性使用?

时间:2012-08-31 15:25:14

标签: java c++ optimization compiler-construction

double calcTaxAmount() {
    double price = getA() * getB() + getC();
    double taxRate = getD() + getE();
    return price * taxRate;
}

上述功能计算纳税金额。

通过调用其他一些功能来计算价格和费率。

我引入了两个局部变量price和taxRate来提高代码可读性,因此两者都只使用一次。 在大多数现代编译器的编译时,这些“一次性”局部变量是否会被替换和内联?

4 个答案:

答案 0 :(得分:4)

一般都是。

Java只会在多次调用代码后将代码优化为本机代码(默认情况下为10,000次)如果该方法不是非常多的调用,则无论如何都不会产生太大的影响。

即使每个产生1 ns的差异,您也需要调用此方法10亿次以添加2秒的延迟。如果只有1000万次你不太可能注意到差异。

答案 1 :(得分:4)

显然,这取决于编译器。在优化方面,相当多的编译器实际上是脑死亡,因为它们处理的动态语言足够复杂,大多数优化都是无效的,而且许多其他编译器只有在满足非常严格的条件时才是安全的(例如,任何函数调用)可能几乎有任何影响)。例如,所有Python实现都有一个编译器,但大多数只做很少的窥孔优化,这可能不足以消除所有开销。

那就是说,如果你在谈论静态类型语言(你的例子暗示),那么通常是的。活动分析可以检测等效性(您仍然需要存储位置,但生命周期是相同的),任何合理的寄存器分配器都可以避免不必要地溢出值。

那就是说,这是一个非常糟糕的优化重点。如果实际想要更快地制作内容,请查看最终代码和配置文件以及实际场景。如果您要进行微观优化,请运用一些常识。即使假设此功能是一个热点,实际计算和获取值可能很容易花费100倍的时间。与堆栈存储相比,非内联函数调用需要相当长的时间,并且缓存未命中在此级别的成本相当

答案 2 :(得分:1)

只要编译器可以证明它们没有别名和外部修改,编译器应该能够优化它们(我怀疑它可以在这里确定)。

如果你制作const,我就无法想到一个无法优化的编译器。

所有这一切,这听起来像过早的优化,即使它的速度稍慢,我也不会改变代码,因为它增加了清晰度。

答案 3 :(得分:1)

完全取决于C的编译器。对于打开了适当优化选项的当前编译器,可能是肯定的。

对于Java, (javac)

据说,这些局部变量无论如何都会增加很少的开销。如果编译器决定将表达式优化为等效于:

 return (getA() * getB() + getC()) * (getD() + getE());

它仍然需要某种形式的临时存储(堆栈或寄存器)来存储子表达式的中间结果。所以它无论如何都不应该有太大的不同。

我不担心它,并提供更好的可读性。