2017-10-18 109 views
0

我主要问的是Java,所以这就是这里的例子,但我希望这适用于其他语言,如C或C++。编译器是否可以识别和优化常用函数?


第一种情况是用于常用功能。它会认识到代码做了某些事情,并用更优化的东西代替它?

易例子:

int max(int a,int b){ 
    return a>b?a:b; 
} 

int rotateLeft(int a,int b){ 
    return (a<<b)|(a>>>-b); 
} 

boolean testBitLittleEndian(int v,int i){ 
    return (v>>i&1)!=0; 
} 

的旋转是不那么明显,但是要解释,所述>>>是无符号/逻辑移位,并且移位量被解释模的宽度。由于int s是32位,因此只使用移位量的最低有效5位。

我认为这是由JIT替代本地旋转指令。

不太明显的错误:

void intToByteLittleEndian(int v,byte[] b,int i){ 
    b[i+3]=(byte)(v>>24); 
    b[i+2]=(byte)(v>>16); 
    b[i+1]=(byte)(v>> 8); 
    b[i ]=(byte) v; 
} 

float median(float a,float b,float c){ 
    float d;//Swap 
    if(a>b){d=a;a=b;b=d;} 
    if(b>c){b=c;} 
    return a>b?a:b; 
} 

甚至还没有接近最佳,但它的简单性和可读性。由于这些函数的变化很多,编译器可能很难检测并正确优化它们。

再次,它可能由JIT来做替换,因为优化版本所需的指令不能从Java获得。

特别针对write int作为小端函数,为了防止编译器可能认为我们可能会编写int的一部分,然后得到越界异常,我们将首先写入最后一个字节。


另一种情况是标准库函数,该编译器可以知道肯定是应该做一些具体的事情。不需要识别和替换代码,因此即使像BigInteger中的数学这样的大功能也可以根据需要进行优化。

Math类是专门用于在可能的情况下用快速原生指令替换的特殊类。

还有一定的那些处于低级语言琐碎,例如Double.doubleToLongBits():如果

int64_t doubleToLongBits(double v){ 
    return *(int64_t*)&v; 
} 

一些更多的工作字节顺序是错误的。

There are others with a pure Java implementation which will be optimized anyways

它也有可能是只有标准库函数都以这种方式进行了优化,因为它很难让编译器知道你的代码做什么,或者其他原因。


主要的原因我听说不能够做这样的优化编译器是他们无法知道你想要什么,或者在这种情况下,你的代码做什么。除了一定的复杂性(这不是很高)之外,编译器会停止以一种可以让它进行优化的方式来分析代码。

+0

您可以随时检查生成的机器码/字节码。当然你不会看到JIT在做什么。 – Henry

+0

问题太广泛了。 Java编译器通常不会优化。 JVM的功能完全取决于所讨论的JVM。你的问题没有单一的答案。 *品牌*,*平台*,*版本*,*版本*。每个组合可能有不同的答案。 – Andreas

+3

@Henry您可以看到由JIT生成的机器代码:[如何在JVM中查看JIT编译的代码?](https://stackoverflow.com/q/1503479/5221149) – Andreas

回答

0

这实际上是一堆问题。但是......

javac优化了什么,这不是它的工作。

的JVM ......没有单一的JVM。有许多实现,他们通常在运行时优化很多。我们来谈谈amd64上的热点。

它可以识别一些模式和一些方法,谷歌的“JVM内部函数”。

例如,Math.max被使用条件移动优化的,如果分析器是这么说的(一个很少被考虑条件分支是平均更快)。

方法,如Integer.rotateLeftLong.rotateRight和其他许多人得到优化的单指令。你自己的代码没有。

位运算的有效执行。

将你的问题的其余部分听起来更像是一个答案......

从这个blog你可以学到很多关于热点的优化。

相关问题