ConcurrentHashMap のパフォーマンスが低下し始める ConcurrencyLevel の最適な値はありますか?
はいの場合、その値は何ですか?また、パフォーマンスが低下する理由は何ですか? (この質問は、ConcurrentHashMap が持つ可能性のある実際的な制限を見つけようとすることから生じています)。
ConcurrentHashMap のパフォーマンスが低下し始める ConcurrencyLevel の最適な値はありますか?
はいの場合、その値は何ですか?また、パフォーマンスが低下する理由は何ですか? (この質問は、ConcurrentHashMap が持つ可能性のある実際的な制限を見つけようとすることから生じています)。
2つの質問を自問する必要があります
最初の質問は、一度にマップにアクセスできるスレッドの最大数を示しています。10000 個のスレッドを持つことができますが、CPU が 4 個しかない場合、一度に実行できるのは最大 4 個です。
2 番目の質問は、これらのスレッドのほとんどがマップにアクセスし、何か役に立つことを行っていることを示しています。マップを最適化して、役に立たないこと (マイクロベンチマークなど) を実行することはできますが、この IMHO を調整するポイントはありません。マップを多用する便利なプログラムがあるとします。IO、他のマップへのアクセス、キーまたは値の作成、マップから取得した値を使用した何かの実行など、他の処理に 90% の時間を費やしている可能性があります。
4 つの CPU を搭載したマシンでマップにアクセスする時間の 10% を費やしているとします。これは、平均して 0.4 スレッドでマップにアクセスすることを意味します。(または、約 40% の時間で 1 つのスレッド) この場合、1 ~ 4 の同時実行レベルで問題ありません。
いずれにせよ、マイクロベンチマークであっても、同時実行レベルを使用している CPU の数よりも高くする必要はありません。
Javadocはかなり詳細なガイダンスを提供します。
更新操作間で許可される同時実行数は、オプションの
concurrencyLevel
コンストラクター引数 (デフォルトは 16) によって決まります。これは、内部サイズ設定のヒントとして使用されます。テーブルは内部的に分割され、指定された数の同時更新を競合なしで許可しようとします。ハッシュ テーブル内の配置は基本的にランダムであるため、実際の同時実行数は異なります。理想的には、同時にテーブルを変更するスレッド数に対応できる値を選択する必要があります。必要以上に高い値を使用すると、スペースと時間が浪費される可能性があり、極端に低い値を使用すると、スレッドの競合が発生する可能性があります。しかし、1 桁以内の過大評価と過小評価は、通常、それほど顕著な影響を及ぼしません。1 つのスレッドのみが変更され、他のすべてのスレッドは読み取りのみが行われることがわかっている場合は、値 1 が適切です。
要約すると、最適な値は、予想される同時更新の数によって異なります。1 桁以内の値が適切に機能するはずです。この範囲外の値は、パフォーマンスの低下につながることが予想されます。