我正在做一些测试,以找出使用getters/setters和直接字段访问之间的速度差异。我写了一个简单的基准测试应用程序是这样的:为什么Method访问看起来比Field访问更快?
public class FieldTest {
private int value = 0;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public static void doTest(int num) {
FieldTest f = new FieldTest();
// test direct field access
long start1 = System.nanoTime();
for (int i = 0; i < num; i++) {
f.value = f.value + 1;
}
f.value = 0;
long diff1 = System.nanoTime() - start1;
// test method field access
long start2 = System.nanoTime();
for (int i = 0; i < num; i++) {
f.setValue(f.getValue() + 1);
}
f.setValue(0);
long diff2 = System.nanoTime() - start2;
// print results
System.out.printf("Field Access: %d ns\n", diff1);
System.out.printf("Method Access: %d ns\n", diff2);
System.out.println();
}
public static void main(String[] args) throws InterruptedException {
int num = 2147483647;
// wait for the VM to warm up
Thread.sleep(1000);
for (int i = 0; i < 10; i++) {
doTest(num);
}
}
}
每当我运行它,我得到一致的结果,如这些:http://pastebin.com/hcAtjVCL
我想知道,如果有人可以给我为什么现场访问,似乎要慢一些解释比getter/setter方法的访问,以及为什么最后8次迭代执行得非常快。
编辑:经考虑assylias
和Stephen C
意见,我已经改变了代码http://pastebin.com/Vzb8hGdc那里我得到了略有不同的结果:http://pastebin.com/wxiDdRix。
我认为编译器内联了getters。你检查过字节码吗? – jlordo 2013-02-12 11:57:09
'/ *等待VM预热*/Thread.sleep(1000);' - 这不是它的工作原理。如果JVM没有做任何事情,它就不会升温......你的微基准有几个缺陷。特别是:(i)您并不真正允许JVM进行预热(ii)您要测试的两个路径采用相同的方法,这可能会阻止某些优化。 – assylias 2013-02-12 11:58:53
@jlordo - 内联由JIT编译器完成。我将不会在字节码中看到。 – 2013-02-12 11:59:12