之前我在Atomic AddOrUpdate on C# Dictionary上提出了一个问题。基本上我得到的答案是扩展C#Dictionary
实现,我发现它非常合理。
我按照建议扩展了Dictionary
实现,然而,性能出乎意料地糟糕!然后我尝试最小化我对C#实现的调整以追踪原因。我可以达到的最小值是:我创建了一个AddOrUpdate
函数,它与Add
具有非常相似的签名,除非它返回bool
,如果字典包含key
并且它的值由给定的value
更新,否则为false。基本上on this source code我做了以下更改:
public bool AddOrUpdate(TKey key, TValue value)
{
return Insert(key, value);
}
和
private bool Insert(TKey key, TValue value)
{
if (buckets == null) Initialize(0);
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
int targetBucket = hashCode % buckets.Length;
for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next)
{
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
{
entries[i].value = value;
version++;
return true; // on original code, it returns void
}
}
int index;
if (freeCount > 0)
{
index = freeList;
freeList = entries[index].next;
freeCount--;
}
else {
if (count == entries.Length)
{
Resize();
targetBucket = hashCode % buckets.Length;
}
index = count;
count++;
}
entries[index].hashCode = hashCode;
entries[index].next = buckets[targetBucket];
entries[index].key = key;
entries[index].value = value;
buckets[targetBucket] = index;
version++;
return false; // on original code, does not return anything
}
我在我的代码上分析了CPU性能,这里有几个快照(注意:lambdas
是修改类型的字典):
比较:最初我的代码没有原子AddOrUpdate大概 2min ,但现在它甚至没有完成!虽然它占用超过 10GB 的RAM并且永远需要!!
我错过了一点吗?
答案 0 :(得分:0)
我想这与您删除IEqualityComparer
的设置有关。
但是,我建议您只使用Insert
方法中的添加标记设置为false
来调用原始AddOrUpdate
,而不是调整插入方法。因为Insert
基本上就像添加或更新方法一样。