【问题标题】:Best way to calculate ETA of an operation?计算操作的 ETA 的最佳方法?
【发布时间】:2010-10-25 13:23:45
【问题描述】:

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

假设我有以下被调用的方法:

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

我有几个想法:

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

【问题讨论】:

  • 无论你选择如何,都不要像微软文件复制进度显示那样做。
  • 非常类似于这个问题:stackoverflow.com/questions/798800/…
  • 非常感谢,之前没找到,现在怎么办? (我第一次在stackoverflow上问:))
  • @JohnBoker 也许我没有注意到。微软是如何做到的?究竟是什么让你产生了这种情绪。我想知道。
  • @TheRealChx101 这是9年前的笑话:xkcd.com/612

标签: math progress time-estimation


【解决方案1】:

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

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

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

【讨论】:

  • 让我们考虑文件下载,实际速度可能会发生很大变化,并且取决于我无法控制的变量。 ETA 对最终用户来说应该是合理的。 (也许我应该更好地澄清这个问题)
【解决方案2】:

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

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%,估计越来越接近事实

【讨论】:

  • 基本但很好的一个,也许您假设操作时间非常一致。在进行估计的时间总是较慢收敛到“实际剩余时间”。 IE:在下载的情况下,可以再次下载完成,我的下载速度会翻倍,此时估计的时间需要很长时间才能准确。
  • 绝对正确,这就是估计的问题。同样可能会开始另一个下载,导致下载速度减半。
  • 我认为您对estimatedRemaining 的计算实际上是为您提供了估计的 时间。你可能想要TimeType estimatedRemaining = (elapsedTime * (total / position)) - elapsedTime
【解决方案3】:

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

第一个没有考虑操作实际变快的情况,说还有10分钟,我3点后回来就结束了。

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

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

【讨论】:

  • 我知道,客户很少注意到,但作为一名软件开发人员,我几乎对这类事情很着迷:)。平均它们是个好主意。
【解决方案4】:

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

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

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

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

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

【讨论】:

    【解决方案5】:

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

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

    • 文件数
    • 文件的大小

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

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

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

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

    这允许用户在知道速度可能会发生变化的情况下做出一些有根据的猜测。并最终减少挫败感。

    【讨论】:

      【解决方案6】:

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

      一些相关链接:

      【讨论】:

      • 非常感谢您提供的链接,我第一次没有注意到它们。现在我又回到了类似的任务中,很想再看看我的问题。
      【解决方案7】:

      在 Python 中:

      >>> done=0.3; duration=10; "time left: %i" % (duration/done-duration)
      'time left: 23'
      

      【讨论】:

      • 你能解释一下你做了什么吗?
      • @KunalMukherjee 当然可以。我通过将操作的持续时间除以完成的数量(> 0 到 1)来计算剩余时间,因此 1(100%)将返回持续时间,我减去它以获得剩余 0 秒。
      【解决方案8】:

      我从事的项目需要 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)
      

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

      【讨论】:

        猜你喜欢
        • 2021-02-05
        • 2020-03-03
        • 2021-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-26
        • 1970-01-01
        相关资源
        最近更新 更多