以下のコードは、まったく同じ計算を 3 回実行します (大したことはありません。基本的には 1 から 100m までのすべての数値を加算します)。最初の 2 つのブロックは、3 番目のブロックよりも約 10 倍速く実行されます。このテスト プログラムを 10 回以上実行しましたが、結果の差異はほとんどありません。
どちらかといえば、3 番目のブロックがより高速に実行される (JIT コンパイル) ことを期待しますが、典型的な出力は次のとおりです。
35974537
36368455
296471550
誰かが何が起こっているのか説明できますか? (明確にするために、ここで何かを修正しようとしているわけではなく、何が起こっているのかをよりよく理解しようとしているだけです)
ノート:
- プログラム中にGCは実行されません(で監視されます
-XX:+PrintGC
) - Oracle JDK バージョン 1.6.0_30、1.7.0_02、および 1.7.0_05 でテスト済み
- 次のパラメータでもテストされています:
-XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m
=> 同じ結果 - 代わりにブロックがループに入れられると、すべての実行が高速になります
- ブロックがメソッドに抽出された場合、すべての実行が高速です (メソッドが 3 回呼び出されても、ループで呼び出されても違いはありません)。
public static void main(String... args) {
//three identical blocks
{
long start = System.nanoTime();
CountByOne c = new CountByOne();
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum += c.getNext();
}
if (sum != c.getSum()) throw new IllegalStateException(); //use sum
long end = System.nanoTime();
System.out.println((end - start));
}
{
long start = System.nanoTime();
CountByOne c = new CountByOne();
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum += c.getNext();
}
if (sum != c.getSum()) throw new IllegalStateException(); //use sum
long end = System.nanoTime();
System.out.println((end - start));
}
{
long start = System.nanoTime();
CountByOne c = new CountByOne();
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum += c.getNext();
}
if (sum != c.getSum()) throw new IllegalStateException(); //use sum
long end = System.nanoTime();
System.out.println((end - start));
}
}
public static class CountByOne {
private int i = 0;
private int sum = 0;
public int getSum() {
return sum;
}
public int getNext() {
i += 1;
sum += i;
return i;
}
}