【问题标题】:Extend C# Dictionary for Atomic AddOrUpdate为 Atomic AddOrUpdate 扩展 C# 字典
【发布时间】:2016-01-21 00:38:29
【问题描述】:

之前我在Atomic AddOrUpdate on C# Dictionary 上问过一个问题。基本上我得到的答案是扩展 C# Dictionary 实现,我觉得这很合理。

我按照建议扩展了Dictionary 实现,但是,性能出奇的差!!然后我尝试尽量减少对 C# 实现的调整以追踪原因。我可以达到的最小值是:我创建了一个AddOrUpdate 函数,它与Add 具有非常相似的签名,除了它返回bool 如果字典包含key 并且它的值由给定的value 更新,否则为假。基本上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 的代码大约需要 2 分钟,但现在它甚至没有完成!而它占用超过 10GB 的 RAM 并且永远占用!!

我错过了一点吗?

【问题讨论】:

    标签: c# .net dictionary atomic


    【解决方案1】:

    我猜这与您删除了IEqualityComparer 的设置有关。

    但是,我建议您直接调用原始的 Insert,并将 false 从您的 AddOrUpdate 方法中设置为 false,而不是调整 Insert 方法。因为那时Insert 的行为基本上类似于添加或更新方法。

    【讨论】:

    • IEqualityComparer ?!不,我没有改变它。基本上比较器总是由TKey 在这种情况和以前的情况下提供。
    • 此外,我看不出带有bool 标志的Insert 可以作为AddOrUpdate 工作,至少通过返回一个boolean 表示密钥已添加或更新。跨度>
    • 如果你看一下代码,你就会明白。 insert 方法首先在循环中检查是否存在与传递给该方法的键类似的键。如果 add 设置为 true ,当存在相同的键时会抛出异常。如果它设置为 false,它将简单地设置新值并返回。当 for 循环完成时,它知道字典中没有提供的键,因此添加它。
    • 好吧,这不是典型的 AddOrUpdate,因为它不返回值。但这不是必需的,因为您只需传递一个值并知道这将是最终存储的值。那么我很困惑。您在设置版本后返回。但是在原始代码中设置版本之后,设置了私有字段比较器。比较器用于 GetHashCode 和 Equals 操作。它不需要 TKey 的比较器,除非您在此问题中未发布的某些代码中设置它
    • 第一点:TKey是一个自定义对象,实现了必要的接口,供字典使用。第二点:我仔细检查了原始代码,version++之后是return,不是比较器。
    猜你喜欢
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多