20


8

Javaでのオートボクシングと手動ボクシング

なぜ2番目のコードが高速なのですか?

Map map = new HashMap();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {
        map.put(i, j);
    }
}

Map map=new HashMap();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {
        map.put(new Integer(i), new Double(j));
    }
}

3 Answer


46


オートボクシングは、内部で小さな整数の整数オブジェクトをキャッシュする「Integer.valueOf」を使用します(デフォルトでは-128〜127ですが、「java.lang.Integer.IntegerCache.high」プロパティで最大値を設定できます-ソースコードを参照してください) Integer.valueOf)であるため、「new Integer」を直接呼び出すこととは異なります。 「Integer.valueOf」は「new Integer」を呼び出す前に整数値の大きさをすばやくチェックするため、「new Integer」を直接呼び出す方が少し高速です(ただし、小さな整数が多い場合はより多くのメモリを使用します) 。 Javaでの割り当ては非常に高速であり、GCを実行する時間は、短命のライブオブジェクトの数に比例します(つまり、 ごみの量に比例しません)、GCも非常に高速です。

ただし、JVMのバージョンと有効化されている最適化に応じて、スカラー置換最適化があります。これは、短命オブジェクトを割り当てるときにパフォーマンスの大幅な違いを生む可能性があります(この例では、最適化を実行できないため、マップ内のオブジェクトですが、他の多くの状況では便利です)。

最近のJVMバージョンには、http://www.ibm.com/developerworks/java/library/j-jtp09275.html [スカラー置換]最適化があります(エスケープ分析がhttp://java.sunである1.6.0_18を除く)。 com / javase / 6 / webnotes / 6u18.html [一時的に無効])。これは、短命のオブジェクトの割り当てを最適化して削除できることを意味します。 JVMのスカラー置換が新しくなったとき、誰かがhttp://blog.juma.me.uk/2008/12/17/objects-with-no-allocation-overhead/ [ベンチマーク]を作成し、そこにあなたと似たコードがありました。 結果は、プリミティブを使用したコードが最速であり、明示的な `new Integer()`呼び出しを使用したコードはプリミティブを使用したものとほぼ同じ速度であり、オートボクシングを使用したコードははるかに低速でした。 これは、オートボクシングが `Integer.valueOf`を使用し、少なくともその時点では、スカラー置換の最適化ではその特殊なケースが考慮されていなかったためです。 それ以来、最適化が改善されたかどうかはわかりません。


14


オートボクシングでは、「Integer.valueOf」と「Double.valueOf」を使用します。 これらのメソッドの呼び出しには、多少のオーバーヘッドがあります(ただし、最終的にインライン化されます)。 また、 `Integer.valueOf`は、プールされたインスタンスを使用するために低い値をチェックしますが、これはコードで頻繁に勝つことはありません(ただし、ヒープサイズを少し減らすことができます)。 プールされたインスタンスは、ヒープサイズ、GC時間を削減し、同等性テストのパフォーマンスを向上させる可能性があります。

しかし、一般的に、それは一般的に無視するべきである微最適化です。


7


マイクロベンチマークの結果は信頼できないので?

また、自動ボクシングは、コンストラクターではなく、Integer.valueOf()およびDouble.valueOf()を使用して行われます。