2013-06-17 21 views
9

この問題の原因は好奇心と効率です。私は特定のループを実行した後に、私は多くの新しいHashSetsを作成していな状況で午前:HashSetを消去して新しいHashSetを作成するメモリ効率

HashSetのは、現在のクラスの先頭にそのように宣言されています

private Set<String> failedTests; 

その後のコードでは、私はちょうど私は、テストを再実行していたときに新しいfailedTestsにHashSetのを作成します。

failedTests = new HashSet<String>(16384); 

は、私がテストのサイズに応じて、何度もこれを行います。ガベージコレクタは、古いデータを最も効率的に処理することを期待しています。

private Set<String> failedTests = new HashSet<String>(16384); 

をして、ループをHashSetのたびにクリア:しかし、私は別のオプションは、最初に、当初のHashSetを作成することです知っています。

failedTests.clear(); 

私の質問は、オーバーヘッドなどの面でこれを行う最も効率的な方法ですか?私はclear()関数が内部で何をしているのか分かりません。古いデータをガベージコレクションに送るのと同じことをやっているのですか?また、HashSetに初期容量の大きなクッションを与えていますが、テストに2^14以上の要素が必要な場合、.clear()関数はHashSetを16384に再インスタンス化しますか?

追加するには、source code to clear() hereが見つかりました。したがって、少なくとも最悪の場合のO(n)操作です。

clear関数を使用して、565秒で終了したテストプロセスを実行しました。 GCを使用してそれを処理すると、テストは506秒で終了しました。

しかし、コンピュータやネットワークのファイルシステムとのインタフェースなどの他の外部要因があるため、完全なベンチマークではありません。しかし、1分は本当にかなり良い感じです。誰かがライン/メソッドレベルで動作する特定のプロファイリングシステムを推奨していますか?

+0

ベンチマークを試しましたか? – rob

+0

あなたは*多くの*新しいセットをあなたが作成している方法に関して何らかの対策がありますか?実際にアプリケーションの動作をテストしましたか? *メモリー対パフォーマンス*の問題のケースで、しばしば時期尚早の最適化につながります。ベースとして、新しい 'HashSet'を作成し、GCがその仕事をし、気になる前に実際の時間を見るために少しプロファイリングすることができます。結局のところ、 'clear'メソッドは反復を伴い、参照をヌルにし、GCがとにかく仕事をすることを可能にします。 – Gamb

+0

可能な複製[forループのArrayListを再作成する最速の方法](http://stackoverflow.com/questions/11740013/fastest-way-to-rec-ate-in-a-for-loop): 'new'は一般的に' clear'よりも速いです。 – assylias

答えて

6

を(私はEclipseのインディゴを使用しています)私はクリア()関数は、それが内部的に使用しているHashMapテーブルのclear()メソッドを呼び出している

の内側にやっているのか分かりません。次のようにHashMapclear()メソッドが定義されています。それは

public void clear() { 
    modCount++; 
    Entry[] tab = table; 
    for (int i = 0; i < tab.length; i++) 
     tab[i] = null; 
    size = 0; 
} 

、同じことをやって、ガーベッジコレクション に古いデータを送信、またはそれも、より効率的な何かをやっているのですか?

tab[i] = nullは、古いデータをガベージコレクションの対象としていると指摘しています。

また、私はテストが以上2^14の要素を必要とする場合、.clear()関数 再インスタンス化HashSetのは16384意志のHashSetに初期容量の大きなクッションを与えるが、 のですか?

いいえ、そうではありません。

これは、オーバーヘッドの点でこれを行う最も効率的な方法です、 などですか?

Javaガベージコレクタは、最も効率的な方法で作業を行う方法を知っています。だからガベージコレクターにこれを世話させてください。だから、私はそれが必要なたびに新しいfailedTests HashSetを作成することを好むでしょう。

+2

大きなオブジェクトはテンポラリスペースにまっすぐに行くので、GCよりも高価です保育園世代の小さなオブジェクトをGCする。それにもかかわらず、このコストは、バッキングアレイのすべての16000要素を反復するコストと比較しても低くなります。 –

4

HashSetを再作成する方が効率的です。

1)HashSetの容量がクリア16384上に成長した場合、初期容量

2にリセットされません)が新しいHashSetの(16384)は新しいエントリー[16384]配列を作成し、それは一つの操作だ、それはヌル要素よりも効率的です1つ1つクリアのように

for (int i = 0; i < table.length; i++) 
    tab[i] = null;