5

IDictionary<TKey,TValue>内部でn個のその他Dictionary<TKey, TValue>を保持し、その挿入をキーのHashCodeによって個々のサブ辞書に配布する実装があります。16 個のサブディクショナリがあるため、4 コア マシンでの衝突の数はかなり少なくなります。

並列挿入の場合、 Add メソッドをReaderWriterLockSlimでロックし、個々のサブ辞書のみをロックします。

  public void Add(TKey key, TValue value)
        {
            int poolIndex = GetPoolIndex(key);
            this.locks[poolIndex].EnterWriteLock();
            try
            {
                this.pools[poolIndex].Add(key, value);
            }
            finally
            {
                this.locks[poolIndex].ExitWriteLock();
            }
        }

4 つのスレッドで項目を挿入すると、約 32% の CPU 使用率しか得られず、パフォーマンスが低下しました。そこで、ReaderWriterLockSlim を Monitor (つまり、lockキーワード) に置き換えました。CPU 使用率はほぼ 100% になり、パフォーマンスは 2 倍以上になりました。

私の質問は、CPU 使用率が増加したのはなぜですか? 衝突の数は変わっていないはずです。ReaderWriterLock.EnterWriteLock が何度も待たされるのはなぜですか?

4

3 に答える 3

13

書き込み専用のロードの場合、Monitor は ReaderWriterLockSlim より安価ですが、読み取りが書き込みよりもはるかに大きい読み取り + 書き込みロードをシミュレートする場合、ReaderWriterLockSlim は Monitor のパフォーマンスを上回ります。

于 2009-01-02T23:47:37.330 に答える
0

私は専門家ではありませんが、RWLS は激しい競合 (数百のスレッドなど)Monitorに向いているのに対し、1 回限りの同期の問題には向いていると思います。

個人的には、タイムアウト パラメータを使用するTimerLockクラスを使用します。Monitor.TryEnter

于 2009-01-02T16:08:58.817 に答える
0

パフォーマンスの低下の原因をどのように知ることができますか? 推測することはできません。唯一の方法は、ある種のプロファイリングを行うことです。

親コレクションのロックをどのように処理しますか、それとも一定ですか?

デバッグ出力を追加して、実際に何が起こるかを確認する必要があるかもしれません。

于 2009-01-02T20:30:31.143 に答える