Collection.Contains Big-O

时间:2012-01-30 13:58:22

标签: c# optimization collections big-o

我需要优化一个显示系统警报数量的功能,当它达到20 000个警报时会变得难以忍受。 (警报由警报和条件组成,这意味着它实际上是40 000个对象)。这个数字每5秒刷新一次。

现在,不要紧,唯一需要的是一个整数,而前一个程序员通过以下方式实现了这个目标:

  1. 每次通话时加载数据库中的每个警报和条件(已确认和未确认)
  2. 遍历每个警报以查找未确认的警报(使用一些自定义Linq扩展名)
  3. 将未确认的警报列表和匹配的条件列表发送到Silverlight应用程序
  4. 将未确认的警报列表与未确认的警报缓存列表进行比较
  5. 重复4.条件
  6. 将标签绑定到Alarms.CountConditions.Count
  7. 这显然会导致很多不必要的开销,我打算通过用SQL语句替换所有内容来解决这个问题

    SELECT COUNT(*) as UnAckAlarms
    FROM Alarms
    WHERE AckTime IS NULL
    

    但不,我想知道的是第4步。 我找到了这个:

    foreach (var alarm in loadResult.Entities)
    {
        if (!ActiveAlarms.Contains(alarm.AlarmId))
        {
            ActiveAlarms.Add(new AlarmInfo
            (...)
    

    报警是一个对象,没有哈希,据我所知,所以我想知道..收集.Contains() O(n)的bigO?在这种情况下,上面的代码不会有O(n ^ 2)吗?而且,如果我通过替换整个集合将此代码优化为O(n),甚至O(1),我会获得0.99%的速度提升吗? (四十○万分之四万^ 2) 或者我应该用SQL语句替换所有内容并重写应用程序的主要部分?

    编辑:所以,有些结果: 优化前:总得分超过60秒 删除不必要的循环后,自定义添加:8秒。服务器加载时间约为7秒,因此: 服务器端优化后:0.3秒。

    速度增加约200%。 :)

2 个答案:

答案 0 :(得分:3)

假设ActiveAlarms类型为CollectionList,并且未使用哈希实现,则Contains()为O(n),代码为以上确实是O(n ^ 2)。

如果您可以将ActiveAlarms更改为哈希集合,则Contains()将为O(1),并且上面的整个代码将变为O(n)。问题是O(1)实际上是否比O(n)快得多,这取决于哈希表的内部哈希函数的复杂程度。但我认为我们可以肯定,在大多数正常情况下它会更快。

您获得的确切速度提升是不可预测的。测量并发现,我会说!

祝你好运!

答案 1 :(得分:1)

我会把这整件事移到sql中。每当添加/删除/确认/等等警报时,创建一组触发器,从运行总计中添加/减去。根本不需要计算事物的运行循环