2009-11-24 64 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秒內使用平均速度,並用剩下的部分進行劃分。如果將當前速度劃分爲整體進度的平均值而不太穩定,則無法處理永久速度變化(如另一次下載正在開始)。