問題は、(今のところ)int
Mapにのようなプリミティブ型を使用して表現できる大量のデータを格納することです。ここでの回答のいくつかは、私の意見では非常に誤解を招くものです。その理由を見てみましょう。
ベンチマークをtroveから変更して、ランタイムとメモリ消費の両方を測定しました。また、このベンチマークにPCJを追加しました。これは、プリミティブ型の別のコレクションライブラリです(これを広範囲に使用しています)。「公式」のtroveベンチマークはIntIntMapsをJava Collectionと比較していませんMap<Integer, Integer>
。おそらく、格納Integers
と格納ints
は技術的な観点から同じではありません。しかし、ユーザーはこの技術的な詳細を気にしないかもしれません。彼はints
効率的に表現できるデータを保存したいと考えています。
まず、コードの関連部分:
new Operation() {
private long usedMem() {
System.gc();
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
// trove
public void ours() {
long mem = usedMem();
TIntIntHashMap ours = new TIntIntHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
ours.put(i, i);
}
mem = usedMem() - mem;
System.err.println("trove " + mem + " bytes");
ours.clear();
}
public void pcj() {
long mem = usedMem();
IntKeyIntMap map = new IntKeyIntOpenHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("pcj " + mem + " bytes");
map.clear();
}
// java collections
public void theirs() {
long mem = usedMem();
Map<Integer, Integer> map = new HashMap<Integer, Integer>(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("java " + mem + " bytes");
map.clear();
}
私はデータがプリミティブとして来ると思いますints
、それは正気のようです。ただし、プリミティブコレクションフレームワークでは不要なオートボクシングのため、これはjava utilの実行時のペナルティを意味します。
gc()
WinXP、jdk1.6.0_10でのランタイム結果(もちろん呼び出しなし):
100000のputオペレーション100000にはオペレーションが含まれます
Javaコレクション1938 ms 203 ms
トローブ234ミリ秒125ミリ秒
pcj 516 ms 94 ms
これはすでに抜本的に思えるかもしれませんが、これがそのようなフレームワークを使用する理由ではありません。
理由はメモリのパフォーマンスです。100000 int
エントリを含むマップの結果:
Javaコレクションが6644536から7168840バイトの間で変動する
trove 1853296バイト
pcj 1866112バイト
Javaコレクションは、プリミティブコレクションフレームワークに比べて3倍以上のメモリを必要とします。つまり、実行時のパフォーマンスを大幅に低下させるディスクIOに頼ることなく、3倍のデータをメモリに保持できます。そして、これは重要です。理由については、スケーラビリティをご覧ください。
私の経験では、高いメモリ消費がJavaの最大のパフォーマンス問題であり、当然、ランタイムパフォーマンスも低下します。プリミティブコレクションフレームワークは、ここで本当に役立ちます。
だから:いいえ、java.utilは答えではありません。また、Javaコレクションに「機能を追加する」ことは、効率性について尋ねるときのポイントではありません。また、最新のJDKコレクションは、「特殊化されたTroveコレクションでもパフォーマンスを向上させる」ことができません。
免責事項:ここでのベンチマークは完全とはほど遠いし、完璧でもありません。これは、私が多くのプロジェクトで経験した要点を理解するためのものです。プリミティブコレクションは、大量のデータを扱う場合に、魚のようなAPIを許容するのに十分役立ちます。