Progress::Any update (2)

This is the second API revision for Progress::Any (0.10). There are a couple of minor incompatibilities introduced, but I think not major like in the first revision a few months ago.

The cause of this second revision is that I want to be able to specify an estimated remaining time even though I haven't given target (or even when target is undefined), or done any update()'s. Plus, I want to do some refactoring to eliminate duplicated code.

Estimating remaining time of tasks

For example, suppose you are writing an installer. You have 3 subtasks: download packages, install the packages, and setup them. After you have done testing on several development machines, you know that the typical average duration for each subtask is respectively, 5, 15, and 10 minutes. You can now say:

package MyInstaller;
use Progress::Any;

sub doit {
    my $pdl = Progress::Any->get_indicator(task=>"download", remaining=>5*60);
    my $pi  = Progress::Any->get_indicator(task=>"install", remaining=>15*60);
    my $ps  = Progress::Any->get_indicator(task=>"setup", remaining=>10*60);


The root task ('') will already have its remaining set to 1800 (30 minutes) which is the total of all its subtasks' remaining. If later in the installer you do:

    for (1..@packages) {
        $pdl->update(pos=>$_, message=>"Downloaded package " . $packages[$_-1]);

later when this code is run, as packages are downloaded you might see remaining decreasing from 30 minutes to 25 minutes, but might temporarily increase to more than 30 minutes if the download speed is slow. But the 25 minutes from the install and setup tasks will still be added to the displayed remaining because those tasks have not been started.

However, if you only output the indicator for download task, you will only get the calculation of remaining for that task. It will start at the preset 30 minutes, but as soon as the first update(), the remaining attribute will be recalculated according to the speed of the update()'s. After the last update(), pos will be equal to target and remaining will be 0.

Accordingly, for the task install the same thing will happen:

    for (1..@packages) {
        $pi->update(pos=>$_, message=>"Installed package " . $packages[$_-1]);

Remaining will start at 25 minutes and will decrease (although might not monotonically) to 10 minutes, at which only the remaining from the setup task remains.

Finally, after the setup task has been completed, remaining will become 0.

Other changes/improvements

  • Add the concept of start()-ing/stop()-ing the task/progress indicator, like a stopwatch. This affects the elapsed time, which won't run if the task is stopped.

  • New template %R to show remaining time or elapsed time, if remaining time cannot be estimated (this happens if you set target to undef, which means that you don't know how many items there are before the task is finished).

  • The $progress export now defaults to Progress::Any->get_indicator(task=>'') (the root task) instead of Progress::Any->get_indicator(task=>'main'), which makes more sense since we by default want to show overall progress for all tasks, instead of just tasks under the main namespace.

The complete list of Changes.

All in all, I'm pretty pleased with this revision.

Leave a comment

About Steven Haryanto

user-pic A programmer (mostly Perl 5 nowadays). My CPAN ID: SHARYANTO. I'm sedusedan on perlmonks. My twitter is stevenharyanto (but I don't tweet much). Follow me on github: sharyanto.