随着时间的推移滑动窗口 - 数据结构和垃圾收集

Posted

技术标签:

【中文标题】随着时间的推移滑动窗口 - 数据结构和垃圾收集【英文标题】:Sliding Window over Time - Data Structure and Garbage Collection 【发布时间】:2013-10-23 13:45:45 【问题描述】:

我正在尝试按照移动平均线来实现一些东西。

在这个系统中,不能保证每个时间段的整数数量。我确实需要计算每个时期的平均值。因此,我不能简单地按数量滑过整数列表,因为这与时间无关。

我可以记录每个值及其相关时间。我们将在系统中运行大量数据,因此“垃圾收集”旧数据非常重要。

还需要注意的是,我需要在每个周期结束后将平均值保存到磁盘。但是,它们可能在将数据保存到磁盘和引入新时期的数据之间存在一些重叠。

我可以使用哪些有效的数据结构来存储、滑动和垃圾收集此类数据?

【问题讨论】:

我提供的答案实际上只是对您的真实需求的猜测。如果我记错了,请告诉我,我会删除它。 让我想起了this question(应用这个问题的答案应该相当简单)。 @rici - 实际上,你成功了。感谢“字里行间”! 【参考方案1】:

问题的描述和问题的冲突:描述的不是移动平均线,因为每个时间段的平均值是不同的。 (“我需要计算每个时期的平均值。”)所以这是一个真正简单的解决方案:

对于每个时期,维护一个计数和观察总和。

在周期结束时,计算平均值

我怀疑实际想要的是:每一秒(计算周期),我想知道过去一分钟(聚合周期)的平均观察值。

这可以简单地通过存储桶的循环缓冲区来解决,每个存储桶代表一个计算周期的值。会有aggregation period / computation period 这样的桶。同样,每个桶都包含一个计数和一个总和。此外,维持当前的总和/和和累积的总和/计数。每个观测值都被添加到当前总数/总和中。

在每个计算周期结束时:

从累计总和/计数中减去(循环)第一期的总和/计数 将当前总和/计数添加到累积总和/计数中 根据累计总和/计数报告平均值 将第一个周期的值替换为当前的总和/计数 清除当前总和/计数 提前循环缓冲区的原点。

如果您确实需要能够随时计算某个给定时间段内先前观测值的所有平均值,则您需要一个更复杂的数据结构,基本上是一个可扩展的循环缓冲区。然而,这种精确的计算实际上很少需要,并且根据上述算法,分桶近似通常足以满足数据目的,并且在内存管理的长期内更具可持续性,因为它的内存需求从一开始就固定.

【讨论】:

就实际数据结构而言,链表很容易实现,因为您只是不断地在其末尾添加新句点。当您需要“垃圾收集”旧数据时,您可以简单地删除链表的元素直到所需的时间。我认为列表不一定需要是循环的。 @andyG:您可以使用链表,但链表中的句点数是恒定的,因此根本不需要内存管理。循环缓冲区是一种非常简单的数据结构(只需使用 i%n 作为索引)。如果您想保留所有观察结果,链表会更简单,但开销非常大,因为每个节点的有效负载大小与指针相当,并且您最终会得到一个缓存不友好的已分配节点集合。您可以将循环缓冲区视为优化内存管理的一种方式。 感谢您澄清这不是移动平均线。我想我需要稍微复习一下我的术语。如果您对标题有任何建议,以免让未来的访客感到困惑,请告诉我! @rici:我的印象是 OP 希望保持所有时期的平均值,而不仅仅是当前时期。循环缓冲区现在有意义了。

以上是关于随着时间的推移滑动窗口 - 数据结构和垃圾收集的主要内容,如果未能解决你的问题,请参考以下文章

如何诊断 Java 8 元空间泄漏?

随着时间的推移,使用熊猫计算滚动窗口中唯一 id 的特定条件事件的数量

JVM 垃圾收集器与内存分配策略

随着时间的推移跟踪文件

如何在熊猫数据框中创建滑动窗口并应用函数

数据仓库 - 随着时间的推移存储独特的数据