性能比较:检查并设置标志Vs.只需设置标志

时间:2014-05-07 11:31:24

标签: c# performance

我有一个标志字典,每个事件都设置了相关的标志。某些事件来自相同类型且具有相同的ID,因此可以多次设置其标志。如果我在设置之前检查一个标志会更快吗?

Dictionary<int, bool> flags = new Dictionary<string, bool>();
foreach(var eventType in eventTypes)
{
    flags.Add(eventType.id, false);
}
for (int i = 0; i < iterations; i++)
{
    // resetting flags for current iteration.
    foreach(var k in flags.Keys)
    {
        flags[k] = false;
    }
    Event[] events = GetEvents();
    foreach(var e in events)
    {
        flags[e.id] = True; // Would it be better to check flag before set it?
    }
    // Do related works for events occurred 
}

3 个答案:

答案 0 :(得分:2)

在这种情况下,当您索引字典时,会发生最昂贵的操作。每当您尝试添加,更新或读取特定密钥的值时,Dictionary需要计算密钥的哈希值,然后获取相应的桶,然后遍历该桶中的元素(如果有更多而不是一个哈希冲突)并将它们与密钥进行比较。

如果您在更新之前检查了该值,则需要执行此操作两次,以防您需要更改该值。

在旁注中,这正是为什么TryGetValue是获取值可能在字典中或不在字典中的首选(更高性能)方法的原因:因为调用ContainsKey然后索引字典将需要两个操作(或者更糟糕的是,捕获KeyNotFoundException)。

此外,如果int键的范围有限,您可以考虑使用BitArray代替Dictionary

<强> [编辑]

据推测,您可以使用字典来检查给定事件是否至少发生过一次。要做到这一点,你可以简单地写:

var eventIds = new HashSet<string>(GetEvents().Select(e => e.Id));

要检查事件是否有效发生,您将查询hashset:

if (eventIds.Contains(id))
{
   // do something
}

答案 1 :(得分:2)

在任何基于字典的操作中,查找时间可能远远超过设置标志所需的时间,这通常只涉及在内存中设置单个值。

如果你只是设置了标志而没有检查,那么只涉及一次查找。

如果先检查,则可能涉及两次查找。但是,编译器很可能会将其优化为单个查找,因此速度可能相似。

结论:

  • 不检查可能更快,但只有在编译器不擅长优化时才会发现这一点

  • 如果您真的关心性能,请考虑是否可以在应用程序中使用数组而不是字典,因为数组往往更快。

然而,这只是基于我的知识和直觉。如果您对性能非常认真,那么唯一真正的解决方案就是编写一些代码来测试各种方法的速度!

答案 2 :(得分:1)

如果标记为false,则仅将标记设置为true较慢,因为您需要两次查询字典。
如果直接设置标志,则只有一个操作。

另外,如果你有一个多线程环境,你还需要防止竞争条件。在&#34;检查和设置&#34;周围加lock逻辑会减慢它的速度。

进行检查的唯一原因我能想到的是,如果你有一个自定义字典,它会在set事件上触发某些事情,即使它是相同的值并且你想避免这种情况。

相关问题