Smart progress bar ETA computation

后端 未结 11 453
谎友^
谎友^ 2020-12-22 16:10

In many applications, we have some progress bar for a file download, for a compression task, for a search, etc. We all often use progress bars to let users know something is

相关标签:
11条回答
  • 2020-12-22 16:25

    Original Answer

    The company that created this site apparently makes a scheduling system that answers this question in the context of employees writing code. The way it works is with Monte Carlo simulation of future based on the past.

    Appendix: Explanation of Monte Carlo

    This is how this algorithm would work in your situation:

    You model your task as a sequence of microtasks, say 1000 of them. Suppose an hour later you completed 100 of them. Now you run the simulation for the remaining 900 steps by randomly selecting 90 completed microtasks, adding their times and multiplying by 10. Here you have an estimate; repeat N times and you have N estimates for the time remaining. Note the average between these estimates will be about 9 hours -- no surprises here. But by presenting the resulting distribution to the user you'll honestly communicate to him the odds, e.g. 'with the probability 90% this will take another 3-15 hours'

    This algorithm, by definition, produces complete result if the task in question can be modeled as a bunch of independent, random microtasks. You can gain a better answer only if you know how the task deviates from this model: for example, installers typically have a download/unpacking/installing tasklist and the speed for one cannot predict the other.

    Appendix: Simplifying Monte Carlo

    I'm not a statistics guru, but I think if you look closer into the simulation in this method, it will always return a normal distribution as a sum of large number of independent random variables. Therefore, you don't need to perform it at all. In fact, you don't even need to store all the completed times, since you'll only need their sum and sum of their squares.

    In maybe not very standard notation,

    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)
    

    With this, you can output the message saying that the thing will end between [lowerBound, upperBound] from now with some fixed probability (should be about 95%, but I probably missed some constant factor).

    0 讨论(0)
  • 2020-12-22 16:27

    Here's what I've found works well! For the first 50% of the task, you assume the rate is constant and extrapolate. The time prediction is very stable and doesn't bounce much.

    Once you pass 50%, you switch computation strategy. You take the fraction of the job left to do (1-p), then look back in time in a history of your own progress, and find (by binary search and linear interpolation) how long it's taken you to do the last (1-p) percentage and use that as your time estimate completion.

    So if you're now 71% done, you have 29% remaining. You look back in your history and find how long ago you were at (71-29=42%) completion. Report that time as your ETA.

    This is naturally adaptive. If you have X amount of work to do, it looks only at the time it took to do the X amount of work. At the end when you're at 99% done, it's using only very fresh, very recent data for the estimate.

    It's not perfect of course but it smoothly changes and is especially accurate at the very end when it's most useful.

    0 讨论(0)
  • 2020-12-22 16:32

    I usually use an Exponential Moving Average to compute the speed of an operation with a smoothing factor of say 0.1 and use that to compute the remaining time. This way all the measured speeds have influence on the current speed, but recent measurements have much more effect than those in the distant past.

    In code it would look something like this:

    alpha = 0.1 # smoothing factor
    ...
    speed = (speed * (1 - alpha)) + (currentSpeed * alpha)
    

    If your tasks are uniform in size, currentSpeed would simply be the time it took to execute the last task. If the tasks have different sizes and you know that one task is supposed to be i,e, twice as long as another, you can divide the time it took to execute the task by its relative size to get the current speed. Using speed you can compute the remaining time by multiplying it by the total size of the remaining tasks (or just by their number if the tasks are uniform).

    Hopefully my explanation is clear enough, it's a bit late in the day.

    0 讨论(0)
  • 2020-12-22 16:37

    I don't sweat it, it's a very small part of an application. I tell them what's going on, and let them go do something else.

    0 讨论(0)
  • 2020-12-22 16:42

    Your question is a good one. If the problem can be broken up into discrete units having an accurate calculation often works best. Unfortunately this may not be the case even if you are installing 50 components each one might be 2% but one of them can be massive. One thing that I have had moderate success with is to clock the cpu and disk and give a decent estimate based on observational data. Knowing that certain check points are really point x allows you some opportunity to correct for environment factors (network, disk activity, CPU load). However this solution is not general in nature due to its reliance on observational data. Using ancillary data such as rpm file size helped me make my progress bars more accurate but they are never bullet proof.

    0 讨论(0)
提交回复
热议问题