我正在寻找使用线性进度信息计算操作的ETA(IE:文件下载)的最佳方法。
让我们说我有以下方法被调用:
void ReportProgress(double position, double total)
{
...
}
我有几个想法:
答案 0 :(得分:7)
我实际上鄙视这两个想法,因为他们以前都是我的开发人员。
第一个没有考虑到操作实际上变快的情况,它说有10分钟的时间我会在3点之后回来并且它已经完成了。
第二个没有考虑到操作变慢 - 我认为Windows资源管理器必须使用这种方法,因为它总是需要90%的时间复制90%的文件,然后另外90%的时间复制最后10%的文件: - )。
我很早就开始计算这些数字并对它们求平均值。客户并不关心(他们也不关心其他两个选项,他们只是想看到一些进展)但它让我感觉更好,而这真的是我所关心的全部一天结束; - )
答案 1 :(得分:6)
这样的事情可以解决问题:
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%,估计值接近事实
答案 2 :(得分:4)
我认为这个问题几乎是无法解决的,但是可以通过更多地了解正在执行的过程来创建一些准确的估计。在存在大量未知数的情况下,最好告知用户这些未知数,以便他们考虑这些未知数。
举一个下载一批文件的简单例子,你有两个已知的变量:
对于每个文件,都有一个不变的开销(建立连接所花费的时间,以及在文件系统上打开文件所花费的时间)。还有与文件大小相关的明显下载时间。根据当前下载速度创建一个可以表示剩余时间的功能很容易,而且如果下载速度不会波动太大,则很准确。但存在问题。
如果没有外部影响,使用您正在执行的操作的准确模型很容易预测需要多长时间。这很少可能。
但是,你可以寻求一种试图理解和解释这些外部影响的解决方案。当速度发生显着变化时,用户可能会发现有助于收到警报,因为他们可以调整计划以适应新的ETA。解释影响当前操作的因素也可能有所帮助。例如
Your download will complete in 6 minutes, if the download speed stays at 50k/s
如果用户知道速度可能会发生变化,则允许用户进行一些有根据的猜测。并最终减少挫折感。
答案 3 :(得分:4)
Bram Cohen已经谈过这个问题了。他在BitTorrent的ETA计算中付出了很多努力(但在一次谈话中,他提到没有人来找他并说“嘿!在bittorrent man中进行了很好的ETA计算!”)。这不是一个简单的问题。
一些相关链接:
答案 4 :(得分:1)
如果你想要一个ETA而不是'进度条'那么你能提供多个数字吗?
计算一段时间内的平均下载速度(取决于整体下载可能会持续多长时间,如果您查看10分钟以上,那么每5秒左右就可以了)并保留记录平均值。
然后你可以提供两个数字,一个上限和下限。
如果您确信平均值将成为下载总时间的良好指示,那么您可以显示第40个百分位数和第60个 - 如果平均下载时间变化很大,那么第10个和第90个可能是更好。
我宁愿看到一个'21-30分钟'的球场,它比29分钟35.2秒更准确,它可以在数英里之外,并且从一次更新变为另一次更新。
答案 5 :(得分:1)
在Python中:
>>> done=0.3; duration=10; "time left: %i" % (duration/done-duration)
'time left: 23'
答案 6 :(得分:0)
这取决于操作时间的一致性。如果它是一致的,那么使用先前操作的平均时间是完全合理的。如果不是,那么你最好定时当前操作并进行外推。
编辑:如果操作与先前的运行不一致,并且从开始到结束也不一致,那么您有一个不可解决的问题。预测不可预测性总是很有趣:)
如果您想低估或高估,可以提前做出决定,并在估算中添加一个软糖因子。例如,如果你想高估,前10%需要6秒,你可以推断为60秒然后乘以1.5得到90秒的总估计值。随着完成百分比的增加,减少软糖因子直到100%变为1.0。
答案 7 :(得分: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)
请注意,该列表具有固定长度,该长度应足够长,以使估算过程“记住” 并适应计算中可能出现的峰值,但也应足够短,可以快速适应计算速度的变化(例如,竞争任务结束后需要更多的计算时间/更多的带宽)