2009-11-24 43 views
10

虽然显示在窗口中的下载状态,我有如下信息:算法中的一个稳定的“下载剩余时间”的下载窗口

1)总文件大小(F)

2)下载的文件大小(F ')

3)当前的下载速度(S)

甲幼稚剩余时间的计算将是(F-F')/(S),但该值的方式,TO-摇摇欲坠(剩余6m /剩余2h /剩余5m!deja vu ?! :)

会有一个既稳定又不极端错误的计算(即使下载即将完成时显示1h)?

+0

我不相信平滑的平均会削减它;我观看了我的Ubuntu更新下载了一半价值的文件,并且我注意到了一个非常明确的模式 - 较大文件的平均速度比较小文件的平均速度要快得多(高达5倍甚至10倍)。如果你对使用的协议做了假设(例如ftp,http),那么你应该能够推断出为什么会发生这种变化(注意由于涉及的所有细节都不容易,但也不是不可能)。基本上,随着时间的推移,我会尝试改进预测下载速度和时间作为大小函数的函数。 – 2010-11-06 17:38:42

回答

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分钟内余长,以至于它平息了违规行为,但仍然逐步适应了更加持久的变化。

+0

不应该是:_count = ** min **(maxsz,count + 1)_? – Felix 2011-05-18 16:01:47

+0

@ phix23:好的。我无法相信没有人注意到,对于一年之后的Annhoo,我修改了它以使其正常工作,并完全消除了对函数的依赖。 – paxdiablo 2011-05-18 23:11:42

+1

我也不敢相信,也许我是第一个真正使用这段代码的人 – Felix 2011-05-18 23:34:05

10

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

+0

谢谢!看起来像一个好地方开始。 – Abhishek 2009-11-24 06:53:21

+0

这实际上就是低通滤波器。 – 2009-11-24 15:13:58

0

为什么不计算下载速度的平均值在整个下载的,那就是:

s = f'/elapsed time 

这样,能够顺利地随着时间的推移。

+3

想到你下载了50%的100kb/s的一小时长的下载。然后你开始另一个下载并且速度下降50kb/s你的下载时间指示器将是错误的,直到你的下载结束。它会说30分钟,而显然将需要我们下载其余的。 – 2009-11-24 06:54:20

+2

其实,你无法预测第二次下载需要多长时间。第二次下载可能总共为50KB。在这种情况下,你会在整个8秒内显示1小时,然后回复到30分钟。预测是困难的,尤其是当涉及到未来:P – MSalters 2009-12-02 10:26:36

4

我更喜欢在最后10秒内使用平均速度,并用剩下的部分进行划分。如果将当前速度划分为整体进度的平均值而不太稳定,则无法处理永久速度变化(如另一次下载正在开始)。