假設以下代碼:原子AddOrUpdate爲C#字典
if (myDictionary.ContainsKey(aKey))
myDictionary[aKey] = aValue;
else
myDictionary.Add(aKey, aValue);
該代碼訪問字典兩次,一次用於確定aKey
是否存在,另一個時間更新(如果存在)或添加(如果它不存在)。我猜這個代碼只執行了幾次,這個方法的性能是「可以接受的」。但是,在我的應用程序中,類似的代碼大約執行了500K次。我對我的代碼進行了描述,它顯示了本節中花費的CPU時間的80%(請參見下圖),因此可以促進改進。
第一個解決辦法很簡單:
myDictionary[aKey] = aValue;
如果aKey
存在它的價值被替換aValue
;如果不存在,則將KeyValuePair
與aKey
作爲關鍵字,並將aValue
作爲值添加到myDictionary
。然而,這種方法有兩個缺點:
第一個,你不知道是否存在aKey
阻止你額外的邏輯。舉例來說,你不能重寫基於此解決方法如下代碼:
int addCounter = 0, updateCounter = 0;
if (myDictionary.ContainsKey(aKey))
{
myDictionary[aKey] = aValue;
addCounter++;
}
else
{
myDictionary.Add(aKey, aValue);
updateCounter++;
}
二,更新不可能是舊值的函數。舉例來說,你不能做類似的邏輯:
if (myDictionary.ContainsKey(aKey))
myDictionary[aKey] = (myDictionary[aKey] * 2) + aValue;
else
myDictionary.Add(aKey, aValue);
第二種解決方法是使用ConcurrentDictionary
。很顯然,使用delegates
我們可以解決上述問題第二;然而,仍然不清楚我們如何解決第一個問題。
只是提醒一下,我的擔心是加速。考慮到只有一個線程正在使用這個過程,我不認爲只有一個線程值得使用ConcurrentDictionary
併發(帶鎖)的懲罰。
我錯過了一個觀點嗎?有沒有人有更好的建議?
只是爲了再次確認:這是單線程的,沒有理由在這裏同步訪問?所以你實際上並不需要一個* atomic *操作,而只是設置一個值的一種快速方法,並確定你是否添加或更新了一個值? – poke
您可以檢查'myDictionary [aKey] = aValue'後的字典中'Count'項目是否已更改以解決第一個缺點。 – ghord
首先,緩存循環範圍變量中的指定區域[_i],然後在另一個循環範圍變量中緩存指定區域[_i] .lambdas。你是否在指定區域看到4.5%的cpu時間?單單這樣做可能會大大加快你的速度。 –