繁体   English   中英

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

[英]Performance Comparison: Check and set a flag Vs. Just set the flag

我有一个标志字典,每个事件我都设置关联的标志。 有些事件来自同一类型,并且具有相同的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 
}

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

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

TryGetValue一句,这就是为什么TryGetValue是首选的(性能更高的)方法来获取可能不在字典中的值的原因:因为调用ContainsKey然后对字典建立索引将需要两项操作(或更糟的是,捕获KeyNotFoundException )。

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

[编辑]

据推测,您可以使用字典检查给定事件是否至少发生了一次。 为此,您可以简单地编写:

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

要检查事件是否有效发生,您可以查询哈希集:

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

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

如果仅设置标志而不进行检查,则仅涉及一次查找。

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

结论:

  • 不检查可能会更快,但这只有在编译器不擅长优化的情况下才会引起注意

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

但是,这只是基于我的知识和直觉。 如果您真的很在意性能,那么唯一真正的解决方案是编写一些代码来测试各种方法的速度!

仅将标志设置为false如果它们为true比较慢,因为您需要查询字典两次。
如果直接设置标志,则仅是一项操作。

另外,如果您具有多线程环境,则还需要防止竞争情况,例如通过在“ check&set”逻辑周围放置一个lock来进一步降低它的运行速度。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM