我想在多线程环境中测量并发字典与字典+锁的性能。所以我创建了自己的 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 关注
- 125 浏览
添加回答
举报
0/150
提交
取消