Main Content

Progress Bar Techniques - Perl

Archive - Originally posted on "The Horse's Mouth" - 2008-12-03 20:33:28 - Graham Ellis

Have you ever sat there and wondered "is this program nearly done ... is it still running ... how is it getting on" and wished you had a progress bar. But then have you ever watched a jerky progress bar and felt that it's more fiction than fact?

We were discussing these aspects on today's private Perl Programming Course (though on our public schedule, this topic is left until Perl for Larger Projects). And we came to the conclusion that progress bars, when carefully implemented, are an excellent idea. So how do you carefully implement them in Perl?

Here is a sample program that I wrote:

select STDERR;
$| = 1;
for (1..14) {
   sleep 1;
   $sofar = $_/14;
   printf "At %4.2f of 1.0\r",$sofar;
   }
print "\n";
$| = 0;
select STDOUT;


And here is a LONG set of notes on a very short program!

Firstly ... the "sleep" represents the work being done and the calculation of "$sofar" represents the calculation of progress so far; it's designed to be awkward and come up with a number that's sometimes a long decimal and at other times is short.

Notes ...

1. The output of the progress bar is to STDERR and not to STDOUT; this is done so that any redirection to file doesn't cause the progress bar data to be dumperd into the file as well, but rather to remain on the screen

2. I've used $| to set autoflush mode so that the progress data is actually output and isn't simply buffered. Normally, Perl buffers up to a \n character but we haven't used any of those right up to the end of the script, so without the setting of $| we would see no report until a sudden flush.

3. \r has been used to return the cursor to the start of the current line rather that to the next line - that way, one progress report overwrites the previous one repeatedly, rather than having them scroll down the screen

4. We've used printf for our output, and used fixed width fields which are plenty long enough for values that are going to be displayed. This means that the line length will NOT change as the program runs, so won't leave "droppings" at the right hand end when a shorter line is displayed over a longer one.

5. There's an indication of just what number we're going up to with our progress bar; we indicate (for example) 0.42 of 1.0 to clearly show that we're 42% of the way through and not just 4.2% or even 0.42%.

And - but it's not explicitly illustrated in this program - I advocate that you should NOT complete one phase of a program that shows a progress bar for that phase, then go onto another section that has its own progress bar ... progress should be reported as to how you're doing through the complete job. I don't know about you, but I have had some VERY frustrating experiences where a long-waited progress bar has finished and joy has turned to dismay as another bar has appeared for some further phase that I didn't even know existed ...

Source code of the example - here