What\'s a good algorithm for determining the remaining time for something to complete? I know how many total lines there are, and how many have completed already, how shoul
Why not?
(linesProcessed / TimeTaken)
(timetaken / linesProcessed) * LinesLeft = TimeLeft
TimeLeft
will then be expressed in whatever unit of time timeTaken
is.
Thanks for the comment you're right this should be:
(TimeTaken / linesProcessed) * linesLeft = timeLeft
so we have
(10 / 100) * 200
= 20 Seconds now 10 seconds go past
(20 / 100) * 200
= 40 Seconds left now 10 more seconds and we process 100 more lines
(30 / 200) * 100
= 15 Seconds and now we all see why the copy file dialog jumps from 3 hours to 30 minutes :-)
How about this....
I used this to walk through a set of records (rows in an Excel file, in one case)
L is the current row number X is the total number of rows dat_Start is set to Now() when the routine begins
Debug.Print Format((L / X), "percent") & vbTab & "Time to go:" & vbTab & Format((DateDiff("n", dat_Start, Now) / L) * (X - L), "00") & ":" & Format(((DateDiff("s", dat_Start, Now) / L) * (X - L)) Mod 60, "00")
Generally, you know three things at any point in time while processing:
Given those items, the estimate (unless the time to process an item is constant) of the remaining time will be
B * C / A
That really depends on what is being done... lines are not enough unless each individual line takes the same amount of time.
The best way (if your lines are not similar) would probably be to look at logical sections of the code find out how long each section takes on average, then use those average timings to estimate progress.
If you know the percentage completed, and you can simply assume that the time scales linearly, something like
timeLeft = timeSoFar * (1/Percentage)
might work.
I'm surprised no one has answered this question with code!
The simple way to calculate time, as answered by @JoshBerke, can be coded as follows:
DateTime startTime = DateTime.Now;
for (int index = 0, count = lines.Count; index < count; index++) {
// Do the processing
...
// Calculate the time remaining:
TimeSpan timeRemaining = TimeSpan.FromTicks(DateTime.Now.Subtract(startTime).Ticks * (count - (index+1)) / (index+1));
// Display the progress to the user
...
}
This simple example works great for simple progress calculation.
However, for a more complicated task, there are many ways this calculation could be improved!
For example, when you're downloading a large file, the download speed could easily fluctuate. To calculate the most accurate "ETA", a good algorithm would be to only consider the past 10 seconds of progress. Check out ETACalculator.cs for an implementation of this algorithm!
ETACalculator.cs is from Progression -- an open source library that I wrote. It defines a very easy-to-use structure for all kinds of "progress calculation". It makes it easy to have nested steps that report different types of progress. If you're concerned about Perceived Performance (as @JoshBerke suggested), it will help you immensely.