9

好奇心と効率性がこの質問の理由です。特定のループが実行された後、多くの新しい HashSet を作成している状況にあります。

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

private Set<String> failedTests;

その後、コードの後半で、テストを再実行するたびに新しい failedTests HashSet を作成します。

failedTests = new HashSet<String>(16384);

テストのサイズに応じて、これを何度も行います。ガベージ コレクターが古いデータを最も効率的に処理することを期待しています。ただし、別のオプションとして、最初に HashSet を最初に作成する方法があることはわかっています。

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

ループのたびに HashSet をクリアします。

failedTests.clear();

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

追加するには、clear() here のソースコードを見つけました。したがって、少なくとも最悪の場合の O(n) 操作です。

クリア機能を使って、565秒で終了するテスト処理を行いました。GC を使用して処理すると、テストは 506 秒で終了しました。

しかし、コンピューターやネットワークのファイル システムとのインターフェイスなど、他の外部要因があるため、これは完璧なベンチマークではありません。しかし、1分間は確かにかなり気分が良い. ライン/メソッドレベルで機能する特定のプロファイリングシステムを推奨する人はいますか? (私はEclipse Indigoを使用しています)

4

2 に答える 2

6

clear() 関数が内部で何をしているのかわかりません

内部で使用しているテーブルのclear()メソッドを呼び出しています。HashMapメソッド内でHashMapclear()、次のように定義されています。

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

古いデータをガベージ コレクションに送信するという同じことを行っているのでしょうか、それともさらに効率的なことを行っているのでしょうか。

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

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

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

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

Java ガベージ コレクターは、最も効率的な方法で作業を行う方法を知っていると思います。したがって、ガベージコレクターにこれを処理させてください。HashSetしたがって、必要になるたびに新しい failedTests を作成することをお勧めします。

于 2013-06-17T20:06:29.087 に答える
5

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

1) HashSet の容量が 16384 を超えた場合、クリアしても初期容量にリセットされません

2) new HashSet(16384) は新しい Entry[16384] 配列を作成します。これは 1 回の操作であり、clear のように要素を 1 つずつ null にするよりも効率的です。

for (int i = 0; i < table.length; i++)
    tab[i] = null;
于 2013-06-17T20:14:33.247 に答える