如何估计剩余的下载时间(准确)?

时间:2010-05-06 08:30:00

标签: algorithm download estimation

当然,您可以将剩余的文件大小除以当前的下载速度,但如果您的下载速度波动(并且它会),则不会产生非常好的结果。什么是更好的算法来产生更平滑的倒计时?

7 个答案:

答案 0 :(得分:113)

exponential moving average非常适合这一点。它提供了一种平滑平均值的方法,这样每次添加新样本时,较旧的样本对整体平均值变得越来越重要。它们仍然被考虑,但它们的重要性呈指数下降 - 因此得名。而且由于它是一个“移动”的平均值,你只需要保留一个数字。

在测量下载速度的上下文中,公式如下所示:

averageSpeed = SMOOTHING_FACTOR * lastSpeed + (1-SMOOTHING_FACTOR) * averageSpeed;

SMOOTHING_FACTOR是介于0和1之间的数字。此数字越大,丢弃的旧样本越快。正如您在公式中所看到的,当SMOOTHING_FACTOR为1时,您只是使用上次观察的值。当SMOOTHING_FACTOR为0时averageSpeed永远不会更改。所以,你想要介于两者之间的东西,通常是一个低值来获得适当的平滑。我发现0.005为平均下载速度提供了非常好的平滑值。

lastSpeed是最后测量的下载速度。您可以通过每秒运行一次计时器来获取此值,以计算自上次运行以来已下载的字节数。

显然,

averageSpeed是您要用来计算估计剩余时间的数字。将其初始化为您获得的第一个lastSpeed测量值。

答案 1 :(得分:7)

speed=speedNow*0.5+speedLastHalfMinute*0.3+speedLastMinute*0.2

答案 2 :(得分:7)

我多年前编写了一个算法来预测磁盘映像和多播程序中剩余的时间,该程序在当前吞吐量超出预定义范围时使用带有重置的移动平均值。它会保持顺畅,除非发生剧烈的事情,然后它会迅速调整,然后再次回到移动平均线。请参见此处的示例图表:

enter image description here

该示例图表中的粗蓝线是随时间变化的实际吞吐量。注意在传输的前半部分吞吐量低,然后在下半部分急剧上升。橙色线是整体平均值。请注意,它从未调整得足够远,无法准确预测完成所需的时间。灰线是移动平均线(即最后N个数据点的平均值 - 在该图中N为5,但实际上,N可能需要更大才能足够平滑)。它恢复得更快,但仍需要一段时间才能调整。较大的N需要更多的时间。因此,如果您的数据非常嘈杂,那么N必须更大,恢复时间也会更长。

绿线是我使用的算法。它就像移动平均线一样,但当数据超出预定范围(由浅蓝色和黄色线指定)时,它会重置移动平均线并立即跳起。预定义范围也可以基于标准偏差,因此可以根据数据的自动噪声进行调整。我只是将这些值扔到Excel中以便为这个答案绘制图表,因此它并不完美,但是你明白了。

可以设计数据以使该算法不能成为剩余时间的良好预测器。最重要的是,您需要大致了解数据的行为方式,并相应地选择算法。我的算法适用于我看到的数据集,因此我们继续使用它。

另一个重要提示是,开发人员通常会忽略进度条和时间估算计算中的设置和拆卸时间。这导致永久的99%或100%进度条长时间坐在那里(当缓存被冲洗或其他清理工作正在发生时)或者在扫描目录或其他设置工作时发生的早期估计,累积时间但不会产生任何百分比的进展,这会导致一切失败。您可以运行包含设置和拆卸时间的多个测试,并根据作业的大小估算这些时间的平均长度,并将该时间添加到进度条。例如,前5%的工作是设置工作,最后10%是拆解工作,然后中间的85%是下载或跟踪的任何重复过程。这也可以提供很多帮助。

答案 3 :(得分:5)

我认为您可以做的最好的事情是将剩余文件大小除以平均下载速度(到目前为止下载的速度除以您下载的时间长度)。这会稍微开始波动,但下载的时间会越来越稳定。

答案 4 :(得分:2)

在扩展到Ben Dolman的答案时,您还可以计算算法中的波动。它会更加流畅,但它也会预测平均速度。

这样的事情:

prediction = 50;
depencySpeed = 200;
stableFactor = .5;
smoothFactor = median(0, abs(lastSpeed - averageSpeed), depencySpeed);
smoothFactor /= (depencySpeed - prediction * (smoothFactor / depencySpeed));
smoothFactor = smoothFactor * (1 - stableFactor) + stableFactor;
averageSpeed = smoothFactor * lastSpeed + (1 - smoothFactor) * averageSpeed;

波动与否,它将与另一个一样稳定,具有正确的预测值和依赖性速度;根据你的网速,你必须玩一点。 这种设置非常适合600 kB / s的平均速度,同时从0到1MB波动。

答案 5 :(得分:1)

我发现Ben Dolman的回答非常有帮助,但是对于像我这样不喜欢数学的人来说,仍然需要大约一个小时才能将其完全实现到我的代码中。这是在python中说相同事情的一种更简单的方法,如果有任何不准确之处让我知道,但是在我的测试中,它工作得很好:

def exponential_moving_average(data, samples=0, smoothing=0.02):
    '''
    data: an array of all values.
    samples: how many previous data samples are avraged. Set to 0 to average all data points.
    smoothing: a value between 0-1, 1 being a linear average (no falloff).
    '''

    if len(data) == 1:
        return data[0]

    if samples == 0 or samples > len(data):
        samples = len(data)

    average = sum(data[-samples:]) / samples
    last_speed = data[-1]
    return (smoothing * last_speed) + ((1 - smoothing) * average)

input_data = [4.5, 8.21, 8.7, 5.8, 3.8, 2.7, 2.5, 7.1, 9.3, 2.1, 3.1, 9.7, 5.1, 6.1, 9.1, 5.0, 1.6, 6.7, 5.5, 3.2] # this would be a constant stream of download speeds as you go, pre-defined here for illustration

data = []
ema_data = []

for sample in input_data:
    data.append(sample)
    average_value = exponential_moving_average(data)
    ema_data.append(average_value)

# print it out for visualization
for i in range(len(data)):
    print("REAL: ", data[i])
    print("EMA:  ", ema_data[i])
    print("--")

答案 6 :(得分:0)

我用这个方程式推导自己。

.

  • E(d)表示下载完成之前剩余的估计时间
  • S(d)表示下载大小
  • L 表示文件已下载部分的大小;和
  • r 表示计算的下载速度

在VB.NET代码中:

Dim ed As TimeSpan = TimeSpan.FromSeconds((sd - l) / r)