14

我正在寻找使用线性进度信息计算操作的 ETA(即:文件下载)的最佳方法。

可以说我有以下被调用的方法:

void ReportProgress(double position, double total)
{
    ...
}

我有几个想法:

  • 计算设定时间内的进度(如最后 10 秒)并将该速度用作操作的平均速度
  • 保留一组已报告的最后 x 个进度,计算每个增量的速度并使用平均值
4

8 回答 8

8

我实际上鄙视这两个想法,因为它们都曾在我作为开发人员之前咬过我。

第一个没有考虑操作实际上变快的情况,它说还有10分钟,我在3后回来,它就完成了。

第二个没有考虑到操作变慢 - 我认为 Windows 资源管理器必须使用这种方法,因为它似乎总是需要 90% 的时间复制 90% 的文件,然后再花 90% 的时间复制最后 10 个文件% 的文件:-)。

我早就开始计算这两个数字并取平均值。客户不在乎(他们也并不真正关心其他两个选项,他们只是想看到一些进展)但这让我感觉更好,这就是我真正关心的一天结束时;- )

于 2009-05-12T13:18:36.540 回答
7

这样的事情应该可以解决问题:

void ReportProgress(double position, double total)
{
    static TimeType startTime;

    if (position == 0)
    {
        startTime = GetTime();
        return; // to avoid a divide-by-zero error
    }

    TimeType elapsedTime = GetTime() - startTime;
    TimeType estimatedRemaining = elapsedTime * total / position;
    TimeType estimatedEndTime = GetTime() + estimatedRemaining;

    // Print the results here
}

随着进度接近 100%,估计值越来越接近事实

于 2009-05-12T13:16:10.043 回答
5

我认为这个问题几乎是无法解决的,但是可以通过对正在执行的过程的更多了解来创建一些准确的估计。在存在大量未知数的情况下,最好将这些未知数告知用户,以便他们将其考虑在内。

以下载一批文件为例,您有两个已知变量:

  • 文件数
  • 文件的大小

对于每个文件,都有固定的开销(建立连接所花费的时间,以及在文件系统上打开文件所花费的时间)。还有与文件大小相关的明显下载时间。创建一个可以根据当前下载速度将其表示为剩余时间的函数很容易并且准确,前提是下载速度不会波动太大。但问题就在这里。

使用您正在执行的操作的准确模型,如果没有外部影响,很容易预测需要多长时间。而这几乎是不可能的。

但是,您可以寻求尝试理解和解释这些外部影响的解决方案。当速度急剧变化时,用户可能会发现收到警报很有帮助,因为他们可以调整计划以适应新的 ETA。解释影响当前操作的因素也可能会有所帮助。例如

Your download will complete in 6 minutes, if the download speed stays at 50k/s

如果用户知道速度可能会改变,这允许用户做出一些有根据的猜测。并最终导致更少的挫败感。

于 2009-05-12T14:29:04.090 回答
4

布拉姆科恩谈到了这一点。他在 BitTorrent 中为 ETA 计算付出了很多努力(但在一次演讲中,他提到还没有人找到他说“嘿!在 bittorrent 中的 ETA 计算很棒!”)。这不是一个简单的问题。

一些相关链接:

于 2009-06-03T08:15:46.617 回答
1

如果您想要 ETA 而不是“进度条”,那么您可以提供多个数字吗?

计算一段时间内的平均下载速度(取决于整体下载可能持续多长时间,如果您正在查看 10 分钟以上,那么每 5 秒左右就可以了)并记录平均值。

然后你可以提供两个数字,一个上限和一个下限。

如果您确信平均值可以很好地指示总下载时间,那么您可以显示第 40 个百分位数和第 60 个百分位数 - 如果平均下载时间差异很大,那么第 10 个和第 90 个百分位数可能会更好。

我宁愿看到一个“21-30 分钟”的球场,它是准确的,而不是被告知 29 分 35.2 秒,而且距离很远,并且从一个更新到下一个更新变化很大。

于 2009-05-12T14:02:57.307 回答
0

这将取决于操作时间的一致性。如果它是一致的,那么使用先前操作的平均时间将是完全合理的。如果不是,您最好对当前操作进行计时并进行推断。

编辑:如果操作与以前的运行不一致,并且从开始到结束也不一致,那么你有一个无法解决的问题。预测不可预知的事情总是很有趣:)

如果您想低估或高估,您可能会提前决定,并在估算中添加一个捏造因素。例如,如果您想高估,而前 10% 需要 6 秒,您可以外推到 60 秒,然后乘以 1.5 得到 90 秒的总估计值。随着完成百分比的增加,减少软糖因子直到 100% 变为 1.0。

于 2009-05-12T13:15:06.893 回答
0

在 Python 中:

>>> done=0.3; duration=10; "time left: %i" % (duration/done-duration)
'time left: 23'
于 2013-08-30T00:23:14.503 回答
0

我从事的项目需要 ETA 进行长时间、耗时的计算,而我最终做的是将过程分成相同大小的批次。然后,我计算每个批次需要多长时间,并将所花费的时间添加到过去计算时间的 FIFO 列表中。

然后对列表中的时间进行平均,并将结果时间乘以剩余的批次数量。

number of batches = N
size of batch = x
past computations length = l (t0,t1,...,tl)
avg time per batch = (t0 + t1 + ... + tl) / l = t
computed batches = n

ETA = t * (N - n)

请注意,该列表具有固定长度,应该足够长以让估计过程“记住”并调整到计算中可能的峰值,但它也应该足够短以快速适应计算速度的变化(例如,更多的计算时间跟随竞争任务的结束/更多带宽)

于 2018-12-05T14:55:52.883 回答