Ideally a progress bar should inform the user how much time is needed for a specific operation. Obviousle the actual time needed will depend on the specific computer, so they typically use a percentage. If the bar goes to 10% in 30 seconds it should be safe to assume that it will need another 4,5 minutes to finish.
But here’s a typical real-life progress bar behavior: It will go to 50% in the first 10 seconds, then jump to 75% after another 60 seconds and then go to 95% and stay there for five minutes.
Why can’t they make a progress bar where the percentage number will correspond with time?
because it’s not omniscient, and can’t predict the transfer speed of the interface you’re transfering data over. if you’re copying a file from a network location, and in the middle of the copy the network is swamped with other traffic, whatever estimate the program had for time to completion is now invalid.
That (the graped section) is exactly what progress bars try to do (well, in general*) - extrapolate the unknown from what is known - but it’s never simple, because it’s subject to available resources, different real-world capabilties of the machine at hand (i.e. a fast CPU on a slow network vs a slow CPU on a fast network, etc)
*In practice, not all progress bars are the same - those that are explicitly coded may jump simply because the only point at which they can be updated is either before or after a single, monolithic operation (for example, an installer that runs as a child process, or a query) - in this case, there just may not be any easy way to track the process within the task - you just have to say it’s 0% done, then it’s 50% done (or whatever)
Progress bars in computers are no different than the “progress bar” in your head. In both cases, you make an estimate based on the current conditions, but can’t know if the conditions will change.
When you stand in line of 4 people at the grocery store, you see 2 people go through with their credit cards in a couple minutes, and the little progress bar in your brain tells you that it will be your turn in another couple minutes.Certain conditions are known— the time to empty their carts, the time to swipe their cards , etc
But then the conditions change: the next person in line wants to pay using 50 coupons, return an item for a refund and then pay with a personal check, all of which need the manager to intervene.
That’s when the progress bar in your brain gets angry.
My app-dev folks tel me that in some of the early days of GUI, people would kick off tasks and wait, without any sort of progress bars they would typically assume the machine was locked up and reboot. Developers began to add progress bar representations to at least show that the device was alive and actively working on something to avoid users screwing things up. As others have mentioned, the bars represent a best guess, all things being equal.
Some progress bars are better than others, depending on what the bottleneck is and how predictable that bottleneck is. If it’s a matter of copying files from one location on your computer to another, the bottleneck is the access speed of the slowest end, which is pretty consistent, and the size of the task is easily measured in bytes. For such a task, the progress bar will be very accurate. For downloading something off of a network, the size of the task is again easily measured, but the speed may or may not be consistent. In this case, the progress bar is sometimes fine, but sometimes gets royally confused. If the bottleneck is a calculation, though, the progress bar usually can’t be any better than a rough guess, since you can’t in general predict how long a calculation will take, short of actually performing it.
Also, I’ll second the difficulty when you’re programming a bar but have no reasonable way of getting status from the child task. All you can do is kick it off and report when it’s done, maybe doing something to inform the user that their PC hasn’t hung (spinning icon or something).
Because it’s hard, for all the reasons that Jas09 lists, and then some.
That’s normally what we do. Do you want a bar that progresses evenly no matter what, or do you want us to fix that problem when you refund orders with tax-free items on them?
Have you ever heard of the “90/90 rule”? The first 90% of any task requires 90% of the time allotted to it; the last 10% takes the other 90% of the time.
Jas09 pegged it. When I was in the software business, I spent a lot of time trying to make the progress bars smooth. A complex process will vary from computer to computer, and the variations are not linear. One computer may have a blazing fast CPU, but a mediocre hard drive and slow network connection. Another may be sitting on a super-fast network, but with a moderate CPU and a slow hard drive. One of the computers may fly through the first half of the process and creep through the last half, and another the exact opposite.
After a while, developers have to ask themselves whether they want to put their efforts into a perfectly smooth progress bar, or into adding another half-dozen spiffy features. Inevitably, the spiffy features win.
In fact, making them more accurate can be a major downside. Windows 8, and, to a lesser extent, Windows 7, came up with ways to make the file copying progress bar more accurate. The result is much slower copies (and, in Windows 8’s case, deletions), because the OS will now go though and check every file size individually and try to calculate how long it will take based on past performance. If you have a lot of files, it’s faster by a factor of at least 200% to copy using a command prompt.
It’s just like it’s often faster to, say, start cleaning up your room rather than go around and estimate how much time it will take to do it.
It all comes down to the program never being 100% certain of how long it will take a particular process to complete.
In the end, it becomes such a nasty problem to solve, and generates so much useless code (in the sense that you won’t find it useful outside of a progress bar) that it’s more reasonable for the developer to make a guess at how long it’ll take. The payoff for a more accurate progress bar is minimal compared to what a code monkey can extrude from his anus in a few minutes.
As with many other problems, it’s more complex than you’d initially think. Suppose you’re installing 100 files, making a progress bar would be very simple wouldn’t it? Just tally how many total files there are and divide it by the number you’ve finished, there is your progress bar percentage. But the files aren’t all the same size. Maybe #1 through #20 are only a few thousand bytes each, and #21 is 2 megabytes. #50 is 10 megabytes. Ok so then you total up the file sizes and use that total as the 100% value. But your operating system is busy doing other things while the copying is going on, maybe it finishes a burst of the first 10 small files in .5 seconds, but then Yahoo Messenger receives a message and alerts you, your e-mail client downloads an attachment, or any one of thousands of other things. Then the next 10 take 1.5 seconds. That screws up the linearity of the progress bar already.
Also, some sort of tasks like searches cannot accurately be forecasted; you don’t know how many results there will be until the search is done.
I don’t think anyone has mentioned another source of delays: waiting for a resource to become available. For example, lots of files have temporary locks put on them, and an installer or file copy might have to wait until a lock is released to continue its progress. Since there’s no telling when the lock will be released, all the designer can really do is generate an error if it’s never released.
I kind of wish programmers would quit estimating and simply provide some descriptors. A file copy operation that says “275/2130 files copied. 1,200/10,587 KB copied. 125 KB/sec current speed.” or “Waiting for file.xxx availability.” would be so much more useful than “12% done” or “2 minutes remaining” and it seems like it would be easier to program too.
Macs don’t show progress bars on startup anymore, but back in the days of Tiger (10.4) they showed a nice blue jelly progress bar while booting. And it moved smoothly.
They cheated.
They used the previous bootup duration to estimate the current boot duration. In other words, if the computer took 2m30s to boot yesterday, today it would show a boot progress bar based on 2m30s total.
To the OP, as a developer I agree with all the stuff about the difficulty in seeing into deeper levels of tasks. If you are only faced with big chunky block tasks, it’s really hard to see into them to the finer details.
These totally phony pseudo-progress-bars are just that: Totally bogus. The only semi-redeeming feature of them is how obviously phony they are. In fact, they are totally useless.
Any process that displays a progress bar like this is really displaying no progress bar at all and that’s what’s so annoying about them. Typically, such a “progress bar” runs as a separate sub-process or thread unto itself, and will keep going round and round indefinitely, even if the actual task at hand is completely stalled.
A huge problem with progress bars is granularity of operations.
Let’s say I’m writing a progress bar, I have to choose when to update its status, and what it’s counting. Well, let’s say I want to count files and update it after every one. Now the progress bar isn’t very representative, a large file gets exactly as much space on the bar as a small file, so you have no idea how long it will take.
So let’s count total bytes, but only update after every file. Okay, but it will still hang like the dickens on large files, but to be fair unless the OS hangs each update will give you a realistic notion of how much work was completed. Still, if you have only three files, two of which are tiny and one of which is huge, you’re not going to get much feedback.
Okay, fine then. Let’s update after every byte written. Great! Well, I hope you like reinventing the wheel. Because now you can’t use the OS’ copy routine, nor the standard library. You have to read the files into memory and output them slowly, byte by byte. Not to mention taking time to update the counter (and maybe redraw the bar) every iteration is likely to slow down the operation, even splitting up the write into that small of chunks is going to add some over head. But hey, at least now you know that the program is hanging if the bar ever stops! While the overhead gets less stiff, the “rolling your own file copy method” problem still applies to any size of granularity below the file level you want to speak of.
Overall, #3 isn’t worth it, and in some cases it’s simply not possible to get a reliable progress update (you may have an easier time in languages like Go or Erlang by using buffered communication between concurrent processes).
I’d say the best option is number 2 – doing it at the file level, but measuring the overall amount of “work” being done. It will still hang, but at least it gives you a semi-realistic picture. (Though you should probably inform the user of the size of the current file so they know why it’s hanging)