java阵列访问如何影响性能?
int steps = 256 * 1024 * 1024;
int[] a = new int[2];
// Loop 1
for (int i=0; i<steps; i++) { a[0]++; a[0]++; }
// Loop 2
for (int i=0; i<steps; i++) { a[0]++; a[1]++; }
有人能解释为什么第二个循环比第一个慢20倍(19毫秒对232毫秒)
这就是我计时的方式:
long start_time = System.currentTimeMillis();
// Loop
long end_time = System.currentTimeMillis();
System.out.println(end_time - start_time);
# 1 楼答案
摘要
JIT编译器正在将第一个循环转换为乘法,但没有对第二个循环进行太多优化
讨论
两个循环的字节码基本相同(您可以使用
javap -c test.class
查看)在Java中,字节码由JIT编译器转换成x86指令,该编译器能够执行额外的优化
如果你有hsdis插件,你可以通过
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly ...
查看JIT生成的程序集我将添加到每个元素的值更改为0xbad,以便更容易发现相关代码,并将循环计数器更改为
long
第一个循环产生:
第二个循环产生:
因此,您可以看到编译器已经能够将第一个循环优化为更少的指令
特别是,它发现对同一数组元素的两个加法可以合并为一个值的两倍的加法
当我将循环计数器改回
int
时,我注意到编译器在第一个循环中做得更好:在本例中,它发现它实际上可以通过使用乘法在一次过程中实现循环的多个迭代!这解释了第一个循环如何比第二个循环快一个数量级