在许多应用程序中,我们都有一些进度条,用于文件下载,压缩任务,搜索等。我们都经常使用进度条让用户知道正在发生的事情。而且,如果我们知道一些细节,例如已完成的工作量和剩余的工作量,我们甚至可以给出时间估计,通常可以通过推断达到当前进度所需的时间来推断。
(来源:jameslao.com)
但是,我们也看到了“Time Left”“ETA”显示的程序可笑。它声称将在20秒内完成文件复制,然后一秒钟后它说将需要4天,然后又闪烁了20分钟。这不仅无益,而且令人困惑!
ETA之所以变化很大,是因为进度本身会变化,并且程序员的数学可能过于敏感。
苹果通过避免任何准确的预测并仅给出模糊的估计来避开这种情况!
(来源:autodesk.com)
这也很烦人,我是否有时间快速休息,还是我的任务将在2秒内完成?如果预测过于模糊,则根本无法进行任何预测。
简单但错误的方法
作为首轮ETA计算,大概我们都可以做一个函数,例如如果p是已经完成的小数百分比,而t是到目前为止所花费的时间,我们输出t *(1-p)/ p作为对p的估计。需要多长时间才能完成。这个简单的比率可以“正常”运行,但也很糟糕,尤其是在计算结束时。如果您的缓慢下载速度使副本在一整夜里缓慢前进,最后在早晨,则出现了一些情况,并且副本开始以全速以100倍的速度全速运行,您的ETA完成了90%时可能会说“1小时”和10秒后来您达到95%,ETA会说“30分钟”,这显然是一个令人尴尬的猜测。.在这种情况下,“10秒”是一个更好得多的估计。
发生这种情况时,您可能会考虑将计算更改为使用最近的速度(而非平均速度)来估计ETA。您可以获取最近10秒钟的平均下载率或完成率,并使用该速率来预测完成时间。在之前的过夜下载(最终速度加快)示例中,该方法的效果很好,因为最终它会给出非常好的最终完成估算值。但这仍然有很大的问题..当您的速率在短时间内快速变化时,它会导致您的ETA剧烈反弹,并且您得到“在20秒内完成,在2小时内完成,在2秒内完成,在30秒内完成分钟”迅速显示出编程的耻辱。
实际问题:
给定计算的时间历史,计算任务完成时间的最佳方法是什么?我不是在寻找指向GUI工具包或Qt库的链接。我问的是算法,它可以生成最合理,最准确的完成时间估算值。
数学公式是否成功?某种平均,可能是通过使用10秒以上的速率的平均值,1分钟以上的速率和1小时以上的速率的平均值?某种人工过滤,例如“如果我的新估计值与先前的估计值相差太大,将其调低,不要让其反弹太多”?某种花式历史分析,您可以在其中整合进度与时间进度,以找到费率的标准偏差,从而在完成时提供统计误差指标?
您尝试过什么,什么最有效?
最佳答案
原始答案
创建此站点的公司apparently makes是一种调度系统,可在员工编写代码的上下文中回答此问题。它的工作方式是基于过去的蒙特卡洛模拟 future 。
附录:蒙特卡洛的解释
这是此算法在您的情况下的工作方式:
您将任务建模为一系列微任务,例如其中的1000个。假设一个小时后您完成了其中的100个。现在,通过随机选择90个已完成的微任务,将它们的时间相乘并乘以10,可以对其余900个步骤进行仿真。重复N次,剩下的时间就有N个估算值。请注意,这些估算值之间的平均时间约为9小时-在此不感到意外。但是,通过将结果分配呈现给用户,您可以诚实地向用户传达赔率,例如“有90%的可能性将再花费3-15个小时”
根据定义,如果所讨论的任务可以建模为一堆独立的随机微任务,则该算法将产生完整的结果。仅当您知道任务如何偏离此模型时,您才能获得更好的答案:例如,安装程序通常具有下载/解包/安装任务列表,并且一个任务的速度无法预测另一个任务。
附录:简化蒙特卡洛
我不是统计学专家,但我认为,如果您仔细研究此方法中的模拟,它将始终返回正态分布,作为大量独立随机变量的总和。因此,您根本不需要执行它。实际上,您甚至不需要存储所有完成的时间,因为您只需要它们的和和它们的平方和。
用也许不是很标准的符号
sigma = sqrt ( sum_of_times_squared-sum_of_times^2 )
scaling = 900/100 // that is (totalSteps - elapsedSteps) / elapsedSteps
lowerBound = sum_of_times*scaling - 3*sigma*sqrt(scaling)
upperBound = sum_of_times*scaling + 3*sigma*sqrt(scaling)
有了这个,您可以输出一条消息,说事情将从现在开始在[lowerBound,upperBound]之间以一定的固定概率结束(应该是95%,但我可能错过了一些恒定因子)。
关于algorithm - 智能进度条ETA计算,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/933242/