- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
假设如下代码:
if (myDictionary.ContainsKey(aKey))
myDictionary[aKey] = aValue;
else
myDictionary.Add(aKey, aValue);
这段代码访问字典两次,一次是判断aKey
是否存在,另一次是更新(如果存在)或者添加(如果不存在)。我想当这段代码只执行几次时,这种方法的性能是“可以接受的”。但是,在我的应用程序中,类似的代码大约执行了 50 万次。我分析了我的代码,它显示 80% 的 CPU 时间花在了这部分(见下图),因此这激发了改进。
第一个解决方法很简单:
myDictionary[aKey] = aValue;
如果 aKey
存在,它的值被替换为 aValue
;如果不存在,则将以aKey
为键,以aValue
为值的KeyValuePair
添加到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
。
我漏掉了一点吗?谁有更好的建议?
最佳答案
如果您真的想要 ConcurrentDictionary
中的 AddOrUpdate
方法,但没有使用它的性能影响,您将必须自己实现这样的 Dictionary。
好消息是,由于 CoreCLR 是开源的,您可以从 CoreCLR repository 获取实际的 .Net 字典源。并应用您自己的修改。看起来不会那么难,看看那里的Insert
私有(private)方法。
一个可能的实现是(未经测试):
public void AddOrUpdate(TKey key, Func<TKey, TValue> adder, Func<TKey, TValue, TValue> updater) {
if( key == null ) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
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 = updater(key, entries[i].value);
version++;
return;
}
}
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 = adder(key);
buckets[targetBucket] = index;
version++;
}
关于c# - C# 字典的原子 AddOrUpdate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33732656/
我正在使用基于代码优先 DBContext 的 EF5 设置。 在 DbMigrationsConfiguration.Seed 中,我试图用默认的虚拟数据填充数据库。为完成此任务,我使用了 DbSe
ConcurrentDictionary Pitfall - Are delegates factories from GetOrAdd and AddOrUpdate synchronized?注意
我有一个ConcurrentDictionary。我使用它的 AddOrUpdate 方法来操作它的项目。 我的问题是:是否可以使用 AddOrUpdate 的更新参数来包含 if 语句?例如。我的
我在我的种子方法中使用 AddOrUpdate 来保持我的权限是最新的,但是,在以下代码更新现有角色(而不是创建它)的情况下,我创建的任何新权限都不会添加到角色。我做错了什么? foreach (Ke
下面是我正在尝试做的事情: 我有 users 表和 user_profiles 表,我在 users 中插入 name、email 表和 phone, address, .... etc 在 user
所以我想做的是添加或更新用户,具体取决于该用户是否已存在于我的种子方法中。 我希望条件是如果具有名字和姓氏的用户已经存在但添加 && 似乎不起作用。 foreach (User user in use
我有 2 个类: class RealmUser: Object { @objc dynamic var id: String = "" @objc dynamic var age:
我正在使用下面的这段代码来尝试根据字典对象的键更新字典对象中的值。 public static ConcurrentDictionary UsersViewModel = new Concurrent
假设如下代码: if (myDictionary.ContainsKey(aKey)) myDictionary[aKey] = aValue; else myDictionary.A
我在播种数据时遇到了一些问题,我能够通过一个非常小的应用程序重现该问题。 假设你有这个种子方法: protected override void Seed(JunkContext contex
我正在按照说明进行操作 here试图 mock 我的 DbSet和 DbContext使用 Moq 进行单元测试。 我正在测试的服务如下所示 public class MyItemService {
IDbSetExtensions.AddOrUpdate 旨在帮助编写无论数据库是空的还是已填充的代码都可以正常工作。但是链接对象需要不同的代码。当数据库为空时,对象还没有 ID,您可以通过分配导航属
private readonly ConcurrentDictionary _colorSet; public void BuildColorSet(IList colorNames, st
这可能是一个简单的问题,但我是 Code First 和迁移的新手,所以请多多包涵。我会将示例代码保持在最低限度以显示问题: 我有一个 BaseAuditableEntity,其中包括这个(除其他外,
在当前项目中,我通过两种方式为并发字典中的现有键赋值。 一个。 concurrentDictionary1[key] = value; 和 B. concurrentDictionary2.AddOr
我有一个实体如下: public class PaletteColor { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Ident
这就是我们拥有的: public class Car { public int Id { get; set; } public Engine Engine { get;
我在 C# 中使用并发字典 addOrUpdate。问题是这个字典不是在维护整个字典(列表),而是它只将最后一条记录添加或更新到字典中,并且该记录在字典中多次找到;我在 foreach 循环中遍历了它
这个问题一直是我周末的噩梦...我有一个表,其中 AddOrUpdate 无法正常工作,它一直在添加但从不更新。 我想做的就是当我使用 AddOrUpdate 将新实体添加到表中时,我希望它检查 Ap
我尝试在 ConcurrentDictionary 中使用 AddOrUpdate 方法。 来自本页的“备注”部分 https://msdn.microsoft.com/en-us/library/d
我是一名优秀的程序员,十分优秀!