【发布时间】:2012-05-25 13:43:59
【问题描述】:
在下面的代码 sn-p 中,Foo1 是一个类,每次调用方法 bar() 时都会增加一个计数器。 Foo2 做同样的事情,但多了一层间接性。
我希望 Foo1 比 Foo2 快,但实际上,Foo2 始终比 Foo1 快 40%。 JVM 是如何优化代码使Foo2 运行速度比Foo1 快的?
一些细节
- 使用
java -server CompositionTest执行测试。 - 使用
java -client CompositionTest运行测试会产生预期结果,即Foo2比Foo1慢。 - 切换循环的顺序没有区别。
- 在 sun 和 openjdk 的 JVM 上使用 java6 验证了结果。
代码
public class CompositionTest {
private static interface DoesBar {
public void bar();
public int count();
public void count(int c);
}
private static final class Foo1 implements DoesBar {
private int count = 0;
public final void bar() { ++count; }
public int count() { return count; }
public void count(int c) { count = c; }
}
private static final class Foo2 implements DoesBar {
private DoesBar bar;
public Foo2(DoesBar bar) { this.bar = bar; }
public final void bar() { bar.bar(); }
public int count() { return bar.count(); }
public void count(int c) { bar.count(c); }
}
public static void main(String[] args) {
long time = 0;
DoesBar bar = null;
int reps = 100000000;
for (int loop = 0; loop < 10; loop++) {
bar = new Foo1();
bar.count(0);
int i = reps;
time = System.nanoTime();
while (i-- > 0) bar.bar();
time = System.nanoTime() - time;
if (reps != bar.count())
throw new Error("reps != bar.count()");
}
System.out.println("Foo1 time: " + time);
for (int loop = 0; loop < 10; loop++) {
bar = new Foo2(new Foo1());
bar.count(0);
int i = reps;
time = System.nanoTime();
while (i-- > 0) bar.bar();
time = System.nanoTime() - time;
if (reps != bar.count())
throw new Error("reps != bar.count()");
}
System.out.println("Foo2 time: " + time);
}
}
【问题讨论】:
-
您是否尝试切换循环以查看是否有所作为?
-
阅读一篇关于 Java microbenchmarking 的优秀 SO 帖子可能是个好主意,然后检查您的代码以确保您的结果确实有意义。
-
我试过了(使用 JRE7 -server),但没有任何区别。什么?!我知道它应该,JRE 需要预热和编译代码,但是......它没有任何区别。完全没有。
-
哇。好问题。我发现,如果您将总体花费的时间加起来(而不仅仅是测量最终循环的计数),那么这两种方法会更接近(尽管奇怪的是 foo2 快了大约 2%)。至于原因呢?
-
@AHungerArtist:切换循环的顺序并没有什么不同。
标签: java performance optimization jvm jit