代码之家  ›  专栏  ›  技术社区  ›  Abhishek

下载窗口中稳定的“剩余下载时间”算法

  •  10
  • Abhishek  · 技术社区  · 15 年前

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

    1)文件总大小(F)

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

    3)当前下载速度

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

    是否会有一个更稳定且不是极端错误的计算(即使在下载即将完成时显示1小时)?

    4 回复  |  直到 14 年前
        1
  •  13
  •   paxdiablo    14 年前

    我们用下面的方法解决了类似的问题。我们对下载速度有多快不感兴趣 整个的 时间,大概是根据最近的活动预计需要多长时间,但是,正如你所说,不是最近的,数据会到处跳跃。

    我们对整个时间段不感兴趣的原因是下载速度可以达到1米/秒,持续半小时,然后在接下来的十分钟内切换到10米/秒。前半个小时会严重拖慢平均速度,尽管你现在正以相当快的速度前进。

    我们创建了一个循环缓冲区,每个单元格保存在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分钟的时间已经足够长,可以消除不规则现象,但仍会逐渐调整为及时进行更永久的更改。

        2
  •  10
  •   Jonathan Graehl    15 年前

    平滑S exponential moving avg . 或类似的)。

        3
  •  4
  •   Cem Kalyoncu    15 年前

    我更喜欢使用过去10秒的平均速度,并用它除以剩余的部分。划分到当前速度太不稳定,而划分到整个进度的平均值无法处理永久的速度更改(就像另一个下载正在启动一样)。

        4
  •  0
  •   Drew Hall    15 年前

    为什么不把下载速度作为整个下载的平均值来计算呢,也就是说:

    s = f' / elapsed time
    

    这样,随着时间的推移,一切都会变得平稳。