ArrayList
を既定の容量と所定の容量で事前初期化してから要件を拡張するまでのパフォーマンスの違いを確認しようとしました。単なる好奇心から。私は、デフォルトの容量アレイコードが〜10%ファーストであることが、アレイを必要な容量に初期化するコードよりも高いことがわかりました。ここで私が使用したコードは次のとおりです。ArrayListのパフォーマンス
public class Test {
public static void main(String[] args) {
long t1 = System.currentTimeMillis();
for(int j=0;j<10;++j) {
List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<1000000;++i) {
list.add(i);
}
}
long t2 = System.currentTimeMillis();
System.out.println("Time taken: " + (t2-t1)/10.0);
}
}
私は一貫して私のボックスで、このバージョンのために〜77ミリ秒を取得し、私はnew ArrayList<Integer>(1000000)
にリストの初期化を変更した場合、私は〜85ミリ秒を取得する一方。それはなぜそうですか?それはそれ以外の方法ではいけませんか?実際、プレ初期化のないリストは、一貫して、普通のInteger[]
を使用するよりもわずかなビット(〜0.5-1ms)で高速です。基本的には、それは挿入のパフォーマンスでdefault capacity arraylist > simple array > pre-capacity-ensured arraylist
と言います。
これは私にとって非常に奇妙です。私の最初の推測では、メモリ割り当てと何か関係があるということです.1000000のintブロックを一度に与えるのは、ゆっくりと余裕を持たせるよりも遅くなるでしょうか?これは他のマシンでも再現可能ですか?私は、Eclipseを実行しているJDK 1.6.0、Mac OS Xを使用しています。
私は別の2つの環境で試しました。 - > Eclipseではなくコマンドラインからjava + javacを実行しようとしました - ここでは一貫してpre-capacity-ensured arraylist > simple array > default capacity arraylist
が得られます。
- > Linux(RHEL)デスクトップでJava + javacを試してみました。このボックスには24 GBのRAMがありますが、ノートパソコンには8 GBしかありませんでした。ここでは、私はplain array >>> default capacity arraylist > pre-capacity-ensured arraylist
を取得します。プレーンアレイは超高速で、この場合、他の2つよりも約2〜3倍高速です。
EDIT:コメントでJonSkeetの提案@以下は、私がnanoTime()
、およびInteger
代わりにint
を使用しました。それでも、JITウォームアップが考慮されていないという問題はまだ解決していません。これらの変更の後、私は一貫してプレーンな配列がすべてのテストで最も速いことを知っています。しかし、容量を保証したリストは、上記の3つの環境全体のデフォルト容量リストと比較して、まだ5〜10%遅くなっています。しかし、一部のユーザーは正しい動作をしているようですので、これは非常に特殊なケースかもしれません。
EDIT2:要素としてIntegerの代わりにStringを使用すると、動作は正しくなります(plain array > pre-capacity-ensured arraylist > default capacity array
)。だから、私はオートバイが実際には犯人だと思う。
を開始するには、これは* *ベンチマークの良い方法ではありません。 JITのウォームアップ時間が含まれており、 'nanoTime'の代わりに' currentTimeMillis'を使用しています。 https://code.google.com/p/caliper/で試してみてください。また、あなたのテストの多くの時間が百万のint値をボクシングに費やしていると思われます。各反復で新しいオブジェクトを作成する必要がない場所で何かを試してみてください。 –
ちょうど役立つヒント:テストを2回実行し、2回目の実行の結果を確認します。最初の実行は、VMオンデマンドロードのために汚染されることがよくあります。 – Kylar
私は外側ループを100反復実行するように変更し、事前割り当てバージョンが約2倍速くなることを発見しました。 –