c# - 快速计算传入数字的最小值、最大值和平均值

标签 c# performance algorithm

程序每秒接收大约 50,000 个数字。

在任何给定时刻,我需要计算在最后一秒(关于给定时刻)到达的值(数字)的最小值、最大值和平均值。

有没有一种方法可以不使用数组或列表(缓冲区)来存储到达的数字和计算结果?

如果我需要使用缓冲区,实现此目的的有效方法是什么?

(请注意,缓冲区中的数字也必须不时有效地删除)

最佳答案

这是一种算法,在某些情况下可以在一定程度上节省效率:

  1. 随着事件的到来,将它们完全缓冲,并计算一个运行的sumcountminmax (琐碎)。

  2. 当请求averageminmax 时,从缓冲区的后面循环并开始删除早于一秒的值。边做边减 sumcount

    • 如果所有值均高于 min,您可以保持 min。如果值低于 max,您可以保留 max。在这种情况下,您可以高效地更新averageminmax

    • 如果值低于 min 或高于 max,您将需要遍历数组的其余部分并重新计算它。

  3. 也大约每秒钟执行一次第二步,这样缓冲区就不会太满。此代码也可以对每个缓冲区插入执行,或者在任何有意义的地方执行。

这种工作的最佳结构是循环缓冲区,以避免内存分配和 GC 妨碍。它应该足够大以涵盖每秒消息大小的最坏情况。

更新

根据使用场景,另一件事是运行上面的算法,但以 10 x 100 毫秒的 block 而不是 1 x 1000 毫秒的 block 运行。也就是说,在这 10 个 block 上保持运行的最小值、最大值、总和和计数。然后,当您到达“无效”场景时,您通常只需要查看最新的 100 毫秒数据或快速浏览其他 9 个 block 的最小值和最大值。


@ja72 提供了一个好主意,可以节省查找无效的最小值和最大值的费用:

与保留最小值/最大值 x_min 不同,x_max 保留它们在 x[i] 数组中的位置索引,其中包含 i_min 和 i_max。有时找到它们可能很简单,但是当考虑的最后一个值包含最小值和最大值时,需要扫描整个列表以建立新的限制。


Sam Holder 在评论中提出了另一个好主意 - 保留一个始终排序的并行数组,这样您就可以从顶部或底部删除数字,以便更轻松地找到新的最小值和最大值。但是,此处的插入速度会有所降低(需要保持顺序)。


最终,正确的选择将取决于程序的使用特性。读取值的频率与插入值的频率是多少?

关于c# - 快速计算传入数字的最小值、最大值和平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10288076/

相关文章:

c# - Xamarin for VS 2015 - 灾难性失败

performance - 提高 Ansible 性能

performance - SQL Server 2008 空间数据功能对映射查询有用吗?

html - IE 中打印网页速度很慢

c# - System.Net.Http.Httpexception 一夜之间失败; "Left with 0 client certificates to choose from."

c# - 在 C# 中找出两个日期的差异

c# - 我应该加密我的 Unity 代码来构建 IOS 游戏吗?

string - Knuth-Morris-Pratt 算法中的 DFA 构造

ruby - 里程表上出现多少次零

algorithm - TOTP 算法是否依赖于始终正确同步的客户端时间?