次のコード スニペットのは、メソッドが呼び出されるFoo1
たびにカウンターをインクリメントするクラスです。同じことを行いますが、間接化のレベルが 1 つ追加されます。bar()
Foo2
Foo1
よりも高速であると期待していますがFoo2
、実際にFoo2
は、常に よりも 40% 高速ですFoo1
。Foo2
よりも高速に実行されるように、JVM はどのようにコードを最適化しています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);
}
}