我需要优化一个显示系统警报数量的功能,当它达到20 000个警报时会变得难以忍受。 (警报由警报和条件组成,这意味着它实际上是40 000个对象)。这个数字每5秒刷新一次。
现在,不要紧,唯一需要的是一个整数,而前一个程序员通过以下方式实现了这个目标:
Alarms.Count
和Conditions.Count
这显然会导致很多不必要的开销,我打算通过用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%。 :)
答案 0 :(得分:3)
假设ActiveAlarms
类型为Collection
或List
,并且未使用哈希实现,则Contains()
为O(n),代码为以上确实是O(n ^ 2)。
如果您可以将ActiveAlarms
更改为哈希集合,则Contains()
将为O(1),并且上面的整个代码将变为O(n)。问题是O(1)实际上是否比O(n)快得多,这取决于哈希表的内部哈希函数的复杂程度。但我认为我们可以肯定,在大多数正常情况下它会更快。
您获得的确切速度提升是不可预测的。测量并发现,我会说!
祝你好运!答案 1 :(得分:1)
我会把这整件事移到sql中。每当添加/删除/确认/等等警报时,创建一组触发器,从运行总计中添加/减去。根本不需要计算事物的运行循环