虽然显示在窗口中的下载状态,我有如下信息:算法中的一个稳定的“下载剩余时间”的下载窗口
1)总文件大小(F)
2)下载的文件大小(F ')
3)当前的下载速度(S)
甲幼稚剩余时间的计算将是(F-F')/(S),但该值的方式,TO-摇摇欲坠(剩余6m /剩余2h /剩余5m!deja vu ?! :)
会有一个既稳定又不极端错误的计算(即使下载即将完成时显示1h)?
虽然显示在窗口中的下载状态,我有如下信息:算法中的一个稳定的“下载剩余时间”的下载窗口
1)总文件大小(F)
2)下载的文件大小(F ')
3)当前的下载速度(S)
甲幼稚剩余时间的计算将是(F-F')/(S),但该值的方式,TO-摇摇欲坠(剩余6m /剩余2h /剩余5m!deja vu ?! :)
会有一个既稳定又不极端错误的计算(即使下载即将完成时显示1h)?
我们通过以下方式解决了类似的问题。我们对下载速度超过整个时间的速度感兴趣,根据最近的活动大概需要多长时间,但正如您所说,不是那么近以至于数字会跳到各处。
我们对整个时间段不感兴趣的原因是,下载可能会在一个半小时内达到1M/s,然后在接下来的十分钟内切换到10M/s。尽管事实上你现在正在以相当快的速度振奋人心,但上半个小时将会严重拖慢平均速度。
我们创建了一个循环缓冲区,每个单元格在1秒内保存下载量。循环缓冲区大小为300,允许5分钟的历史数据,并且每个单元初始化为零。我们还保留了总数(缓冲区中所有条目的总和,所以最初为零)和计数(显然为零)。
每一秒,我们会想出多少数据已经自最后一秒钟,然后下载:
基本上,在伪代码:
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分钟内余长,以至于它平息了违规行为,但仍然逐步适应了更加持久的变化。
平滑s(exponential moving avg。或类似)。
谢谢!看起来像一个好地方开始。 – Abhishek 2009-11-24 06:53:21
这实际上就是低通滤波器。 – 2009-11-24 15:13:58
为什么不计算下载速度的平均值在整个下载的,那就是:
s = f'/elapsed time
这样,能够顺利地随着时间的推移。
想到你下载了50%的100kb/s的一小时长的下载。然后你开始另一个下载并且速度下降50kb/s你的下载时间指示器将是错误的,直到你的下载结束。它会说30分钟,而显然将需要我们下载其余的。 – 2009-11-24 06:54:20
其实,你无法预测第二次下载需要多长时间。第二次下载可能总共为50KB。在这种情况下,你会在整个8秒内显示1小时,然后回复到30分钟。预测是困难的,尤其是当涉及到未来:P – MSalters 2009-12-02 10:26:36
我更喜欢在最后10秒内使用平均速度,并用剩下的部分进行划分。如果将当前速度划分为整体进度的平均值而不太稳定,则无法处理永久速度变化(如另一次下载正在开始)。
我不相信平滑的平均会削减它;我观看了我的Ubuntu更新下载了一半价值的文件,并且我注意到了一个非常明确的模式 - 较大文件的平均速度比较小文件的平均速度要快得多(高达5倍甚至10倍)。如果你对使用的协议做了假设(例如ftp,http),那么你应该能够推断出为什么会发生这种变化(注意由于涉及的所有细节都不容易,但也不是不可能)。基本上,随着时间的推移,我会尝试改进预测下载速度和时间作为大小函数的函数。 – 2010-11-06 17:38:42