我主要问的是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。
它也有可能是只有标准库函数都以这种方式进行了优化,因为它很难让编译器知道你的代码做什么,或者其他原因。
主要的原因我听说不能够做这样的优化编译器是他们无法知道你想要什么,或者在这种情况下,你的代码做什么。除了一定的复杂性(这不是很高)之外,编译器会停止以一种可以让它进行优化的方式来分析代码。
您可以随时检查生成的机器码/字节码。当然你不会看到JIT在做什么。 – Henry
问题太广泛了。 Java编译器通常不会优化。 JVM的功能完全取决于所讨论的JVM。你的问题没有单一的答案。 *品牌*,*平台*,*版本*,*版本*。每个组合可能有不同的答案。 – Andreas
@Henry您可以看到由JIT生成的机器代码:[如何在JVM中查看JIT编译的代码?](https://stackoverflow.com/q/1503479/5221149) – Andreas