5

を使用してマルチスレッド プログラムのベンチマークを行っ-agentlib:hprof=cpu=samples たところ、結果に次の行が含まれていることに驚きました。

rank   self  accum   count trace method
   1 52.88% 52.88%    8486 300050 java.lang.Object.hashCode

プログラムで hashCode() を明示的に呼び出すことはありません。この理由は何ですか?今回の「無駄」の出所と、それが正常か異常かはどうすれば分かるのでしょうか?

ありがとう、デビッド

4

3 に答える 3

5

ほとんどの場合、HashMap などのマップを集中的に使用しています。

HashMap は を使用しhashCodeてオブジェクトを配布しました。このデータ構造を持つ多くのオブジェクトを使用している場合、あなた.equalsとあなたの.hashCodeメソッドが適切に実装されていることが非常に重要です。

参照: 有効な Java 項目 8: equals をオーバーライドするときは常に hashCode をオーバーライドする

于 2010-06-26T16:52:27.343 に答える
1

すべきことの 1 つは、一致するスタック トレースを調べて、誰が呼び出しているかを確認することです。変更は実際に HashMap です。

しかし、これを超えて、hprof は hashCode(); への呼び出しを非常に過大評価する傾向があることに気付きました。その方法と理由を本当に知りたいです。これは、コードの大まかなパフォーマンス プロファイルを実際に知っていることに基づいています。そして、私は 50% パーセントの CPU 使用率 (サンプリングによる) を見てきましたが、そこまで時間がかからないことはほぼ確実です。hashCode() の実装は int フィールドを返すだけで、メソッドは final (final オブジェクト上) です。したがって、これは基本的にある種のプロファイラーのアーティファクトです...どのように、またはなぜ、またはそれを取り除く方法がわかりません。

于 2010-12-07T07:34:05.593 に答える
0

あなたはおそらく正しいでしょう。私は実際にランダム アクセス機能の使用を放棄することができ (それをどのように呼んでいるのでしょうか?)、オブジェクトの順序は気にしません。オブジェクトを追加して、それらすべてを反復処理できるようにする必要があるだけです。また、これは確かにセットです (同じオブジェクトを複数回必要とすることはありません) が、複数回追加しようとすることもありません... 代わりにリストを使用する必要があります (気にしませんが注文)?そのようなセットの最も効率的なデータ構造は何ですか?

HashSet は、キーをそれ自体にマップする HashMap として実装されるため、HashSet に切り替えても、パフォーマンスに関して大きな違いはありません。

他の代替手段は、TreeSet、または (アプリケーションが重複を挿入しようとしないと仮定して) List クラスの 1 つです。List が機能するようなアプリケーションの場合、ArrayList または LinkedList は、HashSet または TreeSet よりも効率的です。

ただし、アプリケーションが時間の 50% をメソッドに費やしていることには、非常に怪しい点がありますhashCode。ハッシュ テーブルのサイズが変更されない限り、hashCode メソッドは、セットまたはマップ操作ごとに 1 回だけ呼び出す必要があります。addしたがって、大量のマップ/セットのサイズ変更が行われているか、膨大な数のセット操作を行っているかのいずれかです。(私の知る限り、オブジェクト ハッシュコード メソッドは安価なので、各呼び出しのコストは問題になりません。)

編集

nextInt() は本当に高価ですか? 代替案はありますか?

いいえ、高価ではありません。コードを見てください。Random クラス (および nextInt() メソッド) は AtomicLong を使用してスレッド セーフにするため、非スレッド セーフ バージョンをコーディングした場合は数サイクルを節約できます。ソースコードはJDKインストールディレクトリにあります...見てください。

于 2010-06-26T17:27:06.690 に答える