Algo在下载窗口中提供稳定的“下载剩余时间”

时间:2009-11-24 06:45:06

标签: algorithm math

在窗口中显示下载状态时,我有以下信息:

1)文件总大小(f)

2)下载文件大小(f')

3)当前下载速度

一个天真的剩余时间计算将是(f-f')/(s),但这个值是不稳定的(剩余6米/剩余2小时/剩余5米!似曾相识?!:)

是否会有更稳定且非极端错误的计算(即使下载即将完成,也会显示1h)?

4 个答案:

答案 0 :(得分:13)

我们通过以下方式解决了类似的问题。我们对下载超过整个时间的速度感兴趣,大概基于最近的活动预计会花多长时间,但正如你所说,不是最近这个数字会是跳到处都是。

我们对整个时间框架不感兴趣的原因是下载速度可以达到1M / s半小时,然后在接下来的十分钟内切换到10M / s。前半个小时将严重拖累平均速度,尽管事实上你现在正在以相当快的速度行走。

我们创建了一个循环缓冲区,每个单元格在1秒钟内保存下载量。循环缓冲区大小为300,允许5分钟的历史数据,每个单元格初始化为零。

我们还维持了一个总数(缓冲区中所有条目的总和,因此最初也为零)和计数(显然为零)。

每一秒,我们都会知道自上一秒以来已经下载了多少数据,然后:

  • 从总数中减去当前单元格。
  • 将当前数字放入该单元格并推进单元格指针。
  • 将当前数字添加到总数中。
  • 如果不是300,则增加计数。
  • 根据总数/计数更新显示给用户的数字。

基本上,在伪代码中:

def init (sz):
    buffer = new int[sz]
    for i = 0 to sz - 1:
        buffer[i] = 0 
    total = 0
    count = 0
    index = 0
    maxsz = sz

def update (kbps):
    total = total - buffer[index] + kbps
    buffer[index] = kbps
    index = (index + 1) % maxsz
    if count < maxsz:
        count = count + 1
    return total / count

您可以更改您的分辨率(1秒)和历史记录(300)以适合您的情况,但我们发现5分钟的时间足够长,以至于平滑了违规行为,但仍然会逐渐适应更持久的变化。

答案 1 :(得分:10)

平滑s(exponential moving avg。或类似)。

答案 2 :(得分:4)

我更喜欢在过去10秒内使用平均速度,并将剩余部分除以此。划分为当前速度太不稳定而划分为整个进度的平均值无法处理永久速度变化(就像另一个下载正在开始)。

答案 3 :(得分:0)

为什么不将下载速度计算为整个下载的平均值,即:

s = f' / elapsed time

这样它会随着时间的推移而平稳。