Java 为什么在循环中使用字段引用之前将其复制到本地?
这个OpenJDK产品线的优势是什么 代码段:Java 为什么在循环中使用字段引用之前将其复制到本地?,java,Java,这个OpenJDK产品线的优势是什么 代码段: private final char value[]; // ... public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; // <--- this line for (int i = 0; i < value.len
private final char value[];
// ...
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value; // <--- this line
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
私有最终字符值[];
// ...
公共int hashCode(){
int h=散列;
如果(h==0&&value.length>0){
char val[]=value;//我查看了字节码,正如@user所评论的,这可能是为了避免循环中的getfield
调用而进行的优化。但是他们弄糟了,仍然在循环条件中引用value变量……所以这实际上使字节码变长变慢了
public int h1() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
public int h2() {
int h = hash;
if (h == 0 && value.length > 0) {
for (int i = 0; i < value.length; i++) {
h = 31 * h + value[i];
}
hash = h;
}
return h;
}
如果他们将循环条件更改为也使用本地字段
...
for (int i = 0; i < val.length; i++) {
...
在我的jdk 1.7.0_79上对该方法进行了数百万次循环的愚蠢测试,结果始终显示原始方法的运行时间是未“优化”或正确“优化”方法的5倍。后两种方法在性能上没有差异
所以我想,总之,本地存储字段是一种试图优化方法字节码的尝试,可能是在jit能够优化它之前,但是他们把它搞砸了,实际上使方法变得更糟
这段代码实际上是用Java 9修复的,
当然,我认为这是多余的,也不明白为什么。这没有好处。即使他们没有复制它。这只是有额外的参考。很好,你发现了这一点1。我认为这是Java开始时留下的。当时没有JIT编译器,通过访问(局部)变量更快-至少这是当时的一个普遍看法。不确定这是否真的是真的(但我在C程序中也看到过这种模式,因为局部变量保存在CPU寄存器中,而实例变量需要从(堆)中读取)记忆。这里有一个类似的问题,看看维维安的答案,我猜可能是和的重复。
...
for (int i = 0; i < val.length; i++) {
...
public int h1();
Code:
0: aload_0
1: getfield #17 // Field hash:I
4: istore_1
5: iload_1
6: ifne 50
9: aload_0
10: getfield #15 // Field value:[C
13: arraylength
14: ifle 50
17: aload_0
18: getfield #15 // Field value:[C
21: astore_2
22: iconst_0
23: istore_3
24: goto 39
27: bipush 31
29: iload_1
30: imul
31: aload_2
32: iload_3
33: caload
34: iadd
35: istore_1
36: iinc 3, 1
39: iload_3
40: aload_2
41: arraylength
42: if_icmplt 27
45: aload_0
46: iload_1
47: putfield #17 // Field hash:I
50: iload_1
51: ireturn