计算剩余下载时间的最佳方法是什么?

时间:2009-04-28 16:33:14

标签: download

假设您要计算剩余的下载时间,并且您拥有所需的所有信息,即:文件大小,dl'ed大小,左侧大小,已用时间,瞬间dl速度等等。 你会如何计算剩余的dl时间?

当然,直接的方式是:尺寸左/瞬间dl速度,或:(经过的时间/尺寸)*尺寸左。 只有第一个会受到瞬时速度偏差的影响,后者不能很好地适应速度变化。

必须是一些更明智的方法,对吧?查看您目前使用uTorrent下载的盗版软件和音乐。很容易注意到它比以前提到的简单计算更有用。实际上,我注意到有时当dl速度下降时,剩余的时间也会下降一段时间,直到它重新调整为止。

7 个答案:

答案 0 :(得分:12)

好吧,正如你所说,使用绝对当前的下载速度并不是一个好方法,因为它往往会波动。然而,像整体平均水平这样的东西也不是一个好主意,因为那里也可能存在很大的波动。

考虑我是否与其他9个人同时开始下载文件。我只获得正常速度的10%,但在文件的中途,另外9个完成。现在我的速度是我开始时的10倍。我最初的10%速度不应该是“剩下多少时间?”的一个因素。再计算。

就个人而言,我可能会在过去30秒左右取平均值,并使用它。这应该根据最近的速度进行计算,而不会大幅波动。 30秒可能不是正确的数量,需要一些实验来计算出好的数量。

另一种选择是设置一种“波动阈值”,在速度变化超过该阈值之前,您不会重新计算。例如(随机数,同样需要实验),您可以将阈值设置为10%。然后,如果您以100kb / s的速度下载,则在下载速度变为低于90kb / s或110kb / s之前,不会重新计算剩余时间。如果发生其中一个更改,则重新计算时间并设置新阈值。

答案 1 :(得分:10)

您可以使用平均算法,其中旧值线性衰减。如果S_n是时间n的速度而A_ {n-1}是时间n-1的平均值,那么定义你的平均速度如下。

A_1 = S_1
A_2 =(S_1 + S_2)/ 2
A_n = S_n /(n-1)+ A_ {n-1}(1-1 /(n-1))

在英语中,这意味着测量过去的时间越长,重要性就越小,因为它的重要性已经衰退。

将此与常规平均算法进行比较: A_n = S_n / n + A_ {n-1}(1-1 / n)

你也可以让它几何衰减,这会对最近的速度造成很大影响: A_n = S_n / 2 + A_ {n-1} / 2

如果速度是4,3,5,6那么 A_4 = 4.5(简单平均值)
A_4 = 4.75(线性衰减)
A_4 = 5.125(几何衰减)

PHP中的示例

请注意$n+1(不是$n)是由于PHP的数组被零索引而导致的当前数据点数。要匹配上述示例集n == $n+1n-1 == $n

<?php

$s = [4,3,5,6];

// average
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
    if ($n == 0)
        $a[$n] = $s[$n];
    else
    {
        // $n+1 = number of data points so far
        $weight = 1/($n+1);

        $a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
    }
}

var_dump($a);


// linear decay
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
    if ($n == 0)
        $a[$n] = $s[$n];

    elseif ($n == 1)
        $a[$n] = ($s[$n] + $s[$n-1]) / 2;

    else
    {
        // $n = number of data points so far - 1
        $weight = 1/($n);

        $a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
    }
}

var_dump($a);


// geometric decay
$a = [];
for ($n = 0; $n < count($s); ++$n)
{
    if ($n == 0)
        $a[$n] = $s[$n];
    else
    {
        $weight = 1/2;

        $a[$n] = $s[$n] * $weight + $a[$n-1] * (1 - $weight);
    }
}

var_dump($a);

输出

array (size=4)
  0 => int 4
  1 => float 3.5
  2 => float 4
  3 => float 4.5

array (size=4)
  0 => int 4
  1 => float 3.5
  2 => float 4.25
  3 => float 4.8333333333333

array (size=4)
  0 => int 4
  1 => float 3.5
  2 => float 4.25
  3 => float 5.125

答案 2 :(得分:7)

显而易见的方法是介于两者之间,你需要一个下载速度的“移动平均线”。

答案 3 :(得分:2)

我认为这只是一种平均算法。它的平均速度只有几秒钟。

答案 4 :(得分:1)

您还可以做的是跟踪您的平均速度并显示其计算结果。

答案 5 :(得分:0)

编辑:这是我最后的建议,我尝试了它,它提供了非常令人满意的结果:

我有一个零初始化数组,每个下载速度在0 - 500 kB / s之间(如果你期望这样的速度,可能会更高),步长为1 kB / s。 我暂时采样下载速度(每秒都是一个很好的间隔),并将相应的数组项增加一。 现在我知道每个速度下载文件花了多少秒。所有这些值的总和是经过的时间(以秒为单位)。这些值的总和乘以相应的速度是到目前为止下载的大小。 如果我取数组中每个值与经过时间之间的比率,假设速度变化模式稳定,我可以形成一个公式来预测每个尺寸所需的时间。在这种情况下,此大小是剩余的大小。我就是做这个的: 我将每个数组项值的总和乘以相应的速度(索引)并除以经过的时间。然后我将该值除以左边的大小,这就是剩下的时间。

需要几秒钟的稳定时间,然后安然无恙地工作。

请注意,这是一个“复杂”的平均值,因此丢弃旧值(移动平均值)的方法可能会进一步改善它。

答案 6 :(得分:0)

对于任何有兴趣的人,我在C#中编写了一个名为Progression的开源库,它具有“移动平均”实现:ETACalculator.cs

Progression库定义了一种易于使用的结构,用于报告多种类型的进度。它还可以轻松处理嵌套进度,以实现非常流畅的进度报告。