我想在多線程環境中測量并發字典與字典+鎖的性能。所以我創建了自己的 SyncDict 類型類<int,int[]>。每當有鍵匹配時,它就會將int[]數組值添加到自身中,并在更新值時使用 ReaderWriterLockSlim 鎖定整個字典。我通過并發字典復制了代碼,我主要使用AddOrUpdate()方法。整個控制臺應用程序代碼可以在這里找到https://dotnetfiddle.net/1kFbGy只需將代碼復制粘貼到控制臺應用程序中即可運行。它不會運行小提琴使用相同的輸入運行兩個代碼后,我發現運行時間有相當大的差異。例如,對于我的機器上的一次特定運行,并發字典花費了 4.5 秒,而 SyncDict 花費了不到 1 秒。我想知道解釋上述運行時間的任何想法/建議。我在這里做錯了什么嗎?class SyncDict<TKey> { private ReaderWriterLockSlim cacheLock; private Dictionary<TKey, int[]> dictionary; public SyncDict() { cacheLock = new ReaderWriterLockSlim(); dictionary = new Dictionary<TKey, int[]>(); } public Dictionary<TKey, int[]> Dictionary { get { return dictionary; } } public int[] Read(TKey key) { cacheLock.EnterReadLock(); try { return dictionary[key]; } finally { cacheLock.ExitReadLock(); } } public void Add(TKey key, int[] value) { cacheLock.EnterWriteLock(); try { dictionary.Add(key, value); } finally { cacheLock.ExitWriteLock(); } } public AddOrUpdateStatus AddOrUpdate(TKey key, int[] value) { cacheLock.EnterUpgradeableReadLock(); try { int[] result = null; if (dictionary.TryGetValue(key, out result)) { if (result == value) return AddOrUpdateStatus.Unchanged; else { cacheLock.EnterWriteLock(); try { Parallel.For(0, value.Length, (i, state) => { result[i] = result[i] + value[i]; });
1 回答

繁星點點滴滴
TA貢獻1803條經驗 獲得超3個贊
您的測試存在多個問題。
1) 您正在使用大約 150.000 個不同的鍵填充字典,所有鍵都具有相同的值。
2) 所有條目的共享值是一個包含 30.000 個整數的數組,并且您將在一半的調用中更新其中的每個元素AddOrUpdate
。但這僅在您測試時才會發生ConcurrentDictionary
。在SyncDict
測試中,有一個條件if (result == value) return AddOrUpdateStatus.Unchanged
會跳過所有更新(因為該值是共享的)。
3)您正在使用不同的隨機輸入來提供兩個測試。
4) 您正在使用循環更新數組Parallel.For
,同時已經處于外部Parallel.For
循環中,從而過度并行化您的工作負載。
5)?調用該方法時,AddOrUpdate
您忽略了記錄的事實,即該updateValueFactory
函數以線程不安全的方式調用,并且由于多個函數AddOrUpdate
是同步執行的并且該值是共享的,因此您正在破壞該值的狀態。
在鎖之外調用委托
updateValueFactory
以避免在鎖下執行未知代碼可能引起的問題。
ConcurrentDictionary.AddOrUpdate 方法
我建議您修改測試以反映該類的預期用途ConcurrentDictionary
。
- 1 回答
- 0 關注
- 163 瀏覽
添加回答
舉報
0/150
提交
取消