我有一个接受时间序列数据的python服务器。现在我需要计算最后一分钟的平均流量,输出像90个样本/分钟。我目前正在使用python列表来保存所有时间戳,并使用一种非常糟糕的方式(在我看来)来计算它。代码大致如下所示:
class TrafficCalculator(object):
timestamps = []
def run():
while True:
# this gets one record of traffic
data = self.accept_data()
# get record's timestamp
timestamp = data.timestamp
# add to list
self.timestamps.append(timestamp)
# get the time one minute ago
minute_ago = timestamp - datetime.timedelta(minutes=1)
# find out the first index of the timestamp in the past that's within 1 minute
for i, t in enumerate(self.timestamp):
if t > minute_ago:
break
# see how many records are within last minute
result = len(self.timestamp[i:])
# throw away the earlier data
self.timestamp = self.timestamp[i:]
正如您所看到的,我必须为每条记录执行此操作,如果我的流量变得很大,那么性能就会很糟糕。
我可以使用更好的数据结构或算法来提高性能吗?更进一步,我如何编写测试来验证我的算法?谢谢!
答案 0 :(得分:4)
使用队列来保留<traffic, timestamp>
对。这里timestamp
是在Queue上推送的时间(从服务器到达)。跟踪队列流量的sum
。当新流量到达并且其时间戳和队列的前面元素的时间戳之间的差异超过1分钟时,从队列弹出前端。并从sum中减去poped流量值。将新流量推入队列并添加到总和。
这样,您的队列就像一个窗口框架一样可以保持1分钟的流量。并且您正在跟踪总和,并且您知道队列大小,因此您可以计算平均值。
空间复杂度为O(maximum traffic can be arrived within 1 minute)
。时间复杂度O(1)
可以随时获得平均值。
对于以恒定时间复杂度的任何正在运行的数据流进行查询,这是一种非常传统的算法。
注意:不幸的是我不懂Python。否则我会把实现。
答案 1 :(得分:1)
你可以用这样的东西来实现它:
data
p=0
sum
变量(尚未初始化)用90个第一个样品填充载体;计算总和并放入变量sum
。
然后:
data[p]
中减去sum
(从总和中移除最旧的样本)p
的向量中
(从而删除最旧的数据); data[p]
添加到sum
(当前金额)p
递增1;如果p
&gt; = 90,则再次p
= 0
(p
指向最早的可用数据)sum/90
等