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

Download 什么';计算剩余下载时间的最佳方法是什么?,download,Download,假设您想要计算剩余的下载时间,并且您拥有所有需要的信息,即:文件大小、下载大小、剩余大小、经过的时间、瞬时下载速度等。 您将如何计算剩余的dl时间 当然,最简单的方法是:左边的大小/瞬时dl速度,或者:(经过的时间/dl’ed大小)*左边的大小。 只是前者会受到瞬时速度偏差的影响,而后者不会很好地适应速度的变化 一定是更聪明的方法,对吧?看看你目前用uTorrent下载的盗版软件和音乐。很容易注意到,它比前面提到的简单计算做得更多。实际上,我注意到,有时当dl速度下降时,剩余的时间也会下降几分钟

假设您想要计算剩余的下载时间,并且您拥有所有需要的信息,即:文件大小、下载大小、剩余大小、经过的时间、瞬时下载速度等。 您将如何计算剩余的dl时间

当然,最简单的方法是:左边的大小/瞬时dl速度,或者:(经过的时间/dl’ed大小)*左边的大小。 只是前者会受到瞬时速度偏差的影响,而后者不会很好地适应速度的变化


一定是更聪明的方法,对吧?看看你目前用uTorrent下载的盗版软件和音乐。很容易注意到,它比前面提到的简单计算做得更多。实际上,我注意到,有时当dl速度下降时,剩余的时间也会下降几分钟,直到它重新调整。

你也可以做的是跟踪你的平均速度,并显示计算结果。

我认为这只是一个平均算法。它在几秒钟内平均下载速度。

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

考虑一下,如果我开始下载的文件与其他9个文件同时下载。我的速度只有我正常速度的10%,但在锉完一半后,剩下的9个完成了。现在我下载的速度是开始时的10倍。我原来10%的速度不应该再成为“还剩多少时间?”计算的一个因素

就我个人而言,我可能会在过去30秒左右取一个平均值,然后使用它。这应该基于最近的速度进行计算,不会出现剧烈波动。30秒可能不是合适的时间,需要一些实验才能找到合适的时间


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

显而易见的方法是介于两者之间,您需要下载速度的“移动平均值”

编辑:以下是我最后的建议,我试过了,结果非常令人满意:

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

需要几秒钟的时间才能稳定下来,然后效果非常好


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

您可以使用一种平均算法,其中旧值线性衰减。如果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+1
n-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);

对于任何感兴趣的人,我用C编写了一个名为的开源库,它有一个“移动平均”实现:


该库定义了一个易于使用的结构,用于报告几种类型的进度。它还可以轻松地处理嵌套进度,以实现非常平滑的进度报告。

如果我错了,请纠正我,但这与我提到的第二个选项相同。您和其他人提到的移动平均值似乎是朝着正确方向迈出的一步,根据我的直觉,它比tresshold方法要好(当然,它们可以结合在一起)。不过,我相信还有更好的方法。我想,速度直方图将是一个巨大的信息量,只需考虑一下这里的lowd。你可以添加一个统计分析,比如:“你的下载在5小时内完成了95%”。更像:“95%的下载时间是以恒定速度进行的,这会产生5小时的下载时间“。我不认为任何用户会接受这样的预测。不,不,我指的是一个更复杂的解决方案,基于对用户下载速度的统计分布的估计。你可以计算分布,然后确定最可能的结果。”
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