54

I'm developing a long-running algorithm and want to give my users an idea of what is the current state of the calculation. I thought of adding a progress bar indicating the percentage of all the calculations already done.

My problem is that the total number of calculations to perform can not be estimated beforehand. I'm somehow discovering a tree and cannot know how vast the tree is without actually exploring it.

With regards to the progress bar it means that the progress bar can sometimes go backward.

For example, let's say that my tree has 10 root elements at the beginning, I perform calculations on the first element so I'm at 1/10 = 10% completion but discover 10 new others elements at the same time, leading to a 1/20 = 5% completion.

Is the progress bar still useful is that case ? I want to avoid to only report X out of Y elements processed.

Is there a better way to report the status of the number of processed elements when the number of elements to process can grow ?

11
  • 13
    "give my users an idea of (...) the percentage of all the calculations already done" and "the total number of calculations to perform can not be estimated beforehand" - these two pretty clearly exclude one another. Commented Jul 25, 2014 at 7:32
  • Maybe a discrete progress bar will help.
    – user5402
    Commented Jul 25, 2014 at 10:19
  • 1
    @O.R.Mapper not necessarily, I can have a pretty good overview of what is done and what need to be done by just looking at which root of the tree I'm working in, but it's not "moving enough" for the users not to feel that the calculation is hanging.
    – strnk
    Commented Jul 25, 2014 at 12:53
  • 3
    @BennySkogberg : that's not related at all. This question is about why the animation of the progress bar goes backward. I'm asking if it's ok if the value of the progress bar goes backward.
    – strnk
    Commented Jul 25, 2014 at 13:27
  • 2
    The only correct use of a reverse progress bar I've seen is for application installation progress when the user clicks cancel before it's complete. While it does its uninstall, the bar goes back to zero. Commented Jul 27, 2014 at 19:37

14 Answers 14

72

If it is possible to traverse the entire tree before beginning processing, I would display an indeterminate progress bar while you discover the branches and then switch to a traditional progress bar once you know the maximum value.

indeterminate progress bar windows

If you cannot identify the total size of the tree before processing, then a progress bar may not be the best option. A progress bar indicates progress towards a known and unchanging maximum. If you don't know the maximum, you can't define the parameters of the progress bar.

In that case, maybe a textual description that is updated in real time would work better. Something like:

Discovered Items: 115

Processed Items: 32

I would definitely not recommend having the progress bar move backwards. This tells the viewer that progress is proceeding backwards or being undone, which is not the case.

7
  • 7
    To add to this, unless your system does not allow scanning alongside processing, I'd start them both at the same time, with the indeterminate being shown first, and switching to the traditional (which should have already partially progressed) once the analysis has finished. That way, you spend the same (or maybe a fraction extra) time compared to doing it witout scanning. When scanning a big tree, it might also be beneficial to show a counter during the scanning. That way, the user does not think the system is hanging.
    – Nzall
    Commented Jul 25, 2014 at 12:07
  • 2
    Unfortunately in my case that would mean that my progress bar would go from the "indeterminate" state to nearly 99%, since I cannot know that I'm processing the last element without actually processing it.
    – strnk
    Commented Jul 25, 2014 at 12:55
  • Consider adding that this scenario is similar to how file managers have been handling it for years.
    – user80551
    Commented Jul 25, 2014 at 13:20
  • 1
    I never really got the point of the everlasting progress bars. You want to convince me that a background process is making progress? Show me something that relates to it! These things can keep spinning regardless of the background. Hate them.
    – Lodewijk
    Commented Jul 25, 2014 at 18:25
  • @strnk Yeah, this only really works if the act of processing is more involved than a simple iteration. Windows update (the image in the answer) can do this because looking for updates cannot know in advance how many updates there are, and downloading them can have such a variable pace that it's hard to predict. but once they're all downloaded, the installation knows how many there are. In fact, I've got a potential answer that might be of some help based on Windows Update.
    – Nzall
    Commented Jul 25, 2014 at 22:23
26

Are you performing a depth first traversal?

When processing a node do you know how many children it has?


If so then one approach is, for any given node assign equal weight to each of the children.

An example:

  • When examining the starting node we find it has two children:

    100 / 2 = 50 so each of these is assigned 50% of the progress bar.

  • When examining the first of these we find three children:

    50 / 3 = 16.7 so each of these is assigned 16.7% of the progress bar.

  • When examining the first of these we find a leaf node:

    We perform the work required by this leaf and then advance the progress bar by the 16.7%

enter image description here

Pros:

The progress bar will move consistently in a forward direction, without any requirement to traverse the tree in advance to count the tasks.

Cons:

Some nodes with fewer children (or easier tasks) will be given undue weight with respect to time. This may make the progress bar appear "jumpy".

3
  • If you'd know how many children there are you could just increment with 0.1% every N/1000 processed nodes/leaves. Point is, he doesn't know.
    – Lodewijk
    Commented Jul 25, 2014 at 18:24
  • 1
    I'm not sure what information @strnk has available. In the example from the question: when processing the starting node it is known to have 10 children (implying knowledge of the current node). Then a further 10 nodes are discovered, it is unclear if these are children or grandchildren of the starting node. If they are grandchildren then the proposed strategy could be applied. However if they are additional children then the N/? problem applies (in a linear manner) to each and every node. In that case it should be solved for the linear case before considering a tree. Commented Jul 26, 2014 at 2:26
  • 2
    He could also just count all the nodes. Usually that sort of operation gets great performance because it can be fully optimized, without branching, perfect prefetch, etc. But he didn't. This is the UX stackexchange, not the algorithms one, so it's clear he wanted a UX answer. I don't see much point in answering a different question, and he didn't give the required information for answering it properly.
    – Lodewijk
    Commented Jul 26, 2014 at 10:58
13

How about making the length of the status bar grow as well? That way, progress goes up even when percent done goes down.

[###-------]                      |30%|  3/10
[####----------------]            |20%|  4/20
[#####---------------------]      |19%|  5/26

It's easier to think about it as two status bars: "work completed" overlaying "total work." The task finishes when they meet, but both can grow.

If the total work exceeds the upper bound (maximum bar length), you will have to rescale and the progress will appear to go backwards visually. The problem you describe -- using a percent with a fixed scrollbar length -- amounts to rescaling every time the total increases.

[#############-----------]      30|54%| 13/24
[##########------------]        60|45%| 20/44

To compensate, you can

  1. Rescale only when the total exceeds the upper bound. The progress will generally go up, and will only "jump" backwards occasionally as the scale changes.
  2. Use a large upper bound.

Since you're dealing with trees, using a logarithmic scale will probably help. I recommend increasing the upper bound by multiplying by some constant (e.g. bound = bound * 1.5).

3
  • 1
    Layout hell? Maybe if you pre-estimate the maximum size you can reserve the space... It's a trade off for resolution in that case.
    – Lodewijk
    Commented Jul 28, 2014 at 13:14
  • I think a logarithmic progress bar would be extremely counterintuitive. Commented Jul 28, 2014 at 17:01
  • I think it's a great idea. Maybe don't use a classic progress bar, but a chart library?
    – keuleJ
    Commented Jul 28, 2014 at 18:44
6

In terms of the particular type of design pattern you are dealing with, I'd say that you are looking at indeterminate progress bar designs. These can be a bit tricky since they generally tend to be very basic, but if you want to provide details then they need to be accurate and not confusing to the user.

My suggestion is that you can probably show the visualization of the tree expanding and that instead of showing the progress bar for the entire process, your progress indicator shows the progress for each individual branch of the tree. So if you hit a new branch point then essentially the previous process has finished and you are starting a new one, but then the user knows that this is just a particular part of the tree and not the entire process.

Basically just imagine a tree where there is a progress bar at each node.

6

Based on the additional information from the comment, the following situation seems to apply:

  • You do not know the total number of nodes on all levels of the tree.
  • You know the number of nodes in the tree down a given level (say, the root level).
  • Just showing the progress within that known number of nodes down to a given level will not show enough "movement".

Therefore, I'd opt for expressing the progress within the known range as a progress bar, and combining or overlaying it with a label that displays something that changes frequently, such as the name of the current node or subtree. That shows users that there is some activity; if your application actually does end up hanging, they have something for the bug report that indicates where exactly the process froze, and it is some information that does not require any knowledge about the complete extent of the subtree in question.

1
  • +1 for "and combining or overlaying it with a label that displays something that changes frequently, such as the name of the current node or subtree". Commented Jul 28, 2014 at 15:18
6

YES!

A progressbar shows the best-available estimate of completion. Ideally it would move entirely smoothly and the progress should finish at exactly the moment it hits 100%. In reality progress estimates always suck and progress bars are jumpy.

Please, for the love of life, try as hard as you can to be honest with users. Give them the best available estimate.

But, if you really want to seem smug, you can let it wait until reality catches up. It might give users a better experience than going backwards. What can I say? Most people are used to the lies.

3

I do think it is weird to go backward. If you just need something basic and visual, you could specify that the progress bar is only updated when it shows advancement. That may result in fast initial progress and then jumpy progress after that but many progress bars work that way anyway.

You could alternatively show the two numbers (45 completed / 345 waiting) and then grow the numbers real time. I know I've seen some searches work this way but can't recall where.

3

Without a good way of estimating, you are better off not estimating - rolling back would count as a form of bad estimate, and should be avoided - perhaps instead display the number of elements processed and a time taken, and allow the user to do the logic of "When I did this last time, it had 10k elements, this time it has 15k..."

3

I've seen many applications that use two progress bars. For example: one progress bar that indicates the overall progress, and the second one shows the progress of current item. This way, some items can be fast and others slow. The overal process are for example the number of subtrees at level two of your tree that are already processed. Current item might depend on level three.

mockup


Real life example:

enter image description here
(Original post here)

4
  • 1
    And what is your proposed implementation for figuring out how much of the "overall" task has been completed given the lack of prior information mentioned in the question. Commented Jul 28, 2014 at 13:03
  • Well, instead of traversing the whole tree, limit it to the second level in the the tree. Take that amount as the max for the overall process. For the current task, traverse the subtree and count the number of elements at level 4, and use that as max for the current item. Commented Jul 28, 2014 at 13:16
  • 1
    Sorry, but didn't Nate Kerkhofs suggest that already, along with a list of the cons of such a approach? Commented Jul 28, 2014 at 15:17
  • Yes, indeed. I didn't read all the posts. I just searched for someone proposing two progress bars. Commented Jul 28, 2014 at 16:44
3

Since many answers imply that user experience may suffer with indeterminate progress bars, or a progress which is slowing down/jumping/moving backwards, here an another approach similar to how many computer games with longer loading times solve it:

Processing Level 1 Nodes...
[#######----------] 35% done

Simply start with "Processing level 1 Nodes" and just use a good guess, how many nodes there are going to be. Make your Progress bar show accurate process while processing nodes. The discovery of new nodes is not shown in any way, until the first progress-bar is at 100% (So if your first estimate was 20 Nodes, it will be at 100% after 20 Nodes are processed, even if there are now 70 Nodes more to process)

Then change the text in the top, so the user will see, that a second step in the Operation has begun! Reset the progress bar to 0% and use the new estimate as the calculation factor. So if there are another 50 Node estimated to process, each node will add 2%

Processing Level 2 Nodes...
[#----------------] 2% done

The User will always experience a smooth progress of the bar and will probably have a slightly better feeling than a complete indeterminate bar. And he will not question, if the program is stuck or something, because there are actually always new levels being processed. When using the application many times, he might even get a feel for the number of levels to expect.

EDIT: These "Level X" Numbers don't have to correspond to an actual depth-level in the tree or actual logical processing steps in your code. They are just "First estimate", "Second estimate" and so on... Just arbitrary numbers so the user will always get the feeling - there is some more "new" work to be done, but the processing is still fast and smooth

2

Some research I recall on progress bars had found that if the display of progress just pauses or slows down this would be reason for user concern and their perception of elapsed time would increase.

As per other answer displaying the number of units completed is positive. As is displaying number known items so far. Indicating rate of units completed per time interval is useful as this information can help with identifying any issues, supports a perception of efficiency and user driven estimation.

Absolutely key though is to indicate when no more items will be added to the list i.e. When discovery process is finished.

Very useful is to indicate the how and why of the discovery process so users have no surprise when number of items remaining increases.

1
  • +1: "...indicate when no more items will be added". Perhaps you could also consider adding the progress bar (already part-completed) at this point, because then your maximum will be defined and unchanging.
    – ArtOfCode
    Commented Jul 25, 2014 at 8:53
2

It seems like your app is a lot like an antivirus software.

Like mentioned before, you might want to just have a text only indicator. If you're really set on a progress bar, perhaps do a marquee first to scan the tree up to a certain level to scan for the number of "main" branches, and then use that and hope that it works good enough.

You could also experiment with slowly decreasing the value of the progress bar, and limiting it to around 10% decrease. No user should notice this if it's small and gradual. If you want to trick the eye to make it less noticeable, you could also add some animations so it still seems like it's about the same.

2

How about making it explicitly clear that the total is still being updated and the confidence in the % value is low / subject to change?

This is a modified version of the approach taken by 'WinMerge' when scanning through multiple directories (trees of nodes):

**Progress**
Total items: 500 (still scanning for more..)
Proccessed: 100 (~20%)

.. which 'jumps' back to:

**Progress**
Total items: 1500 (still scanning for more..)
Proccessed: 150 (~10%)

.. which then evolves to:

**Progress**
Total items: 2000
Proccessed: 1000 (50%)
2

Here's my suggestion: you cannot know the size of the ENTIRE tree in advance. However, you do know how many objects are directly below the root, and once you scan one level deep, you also know how many objects are in the Nth object directly on the root. combining these 2 things, you might be able to use a dual progress bar setup, where you have 1 progress bar for the root level objects, and your second progress bar refers to the elements that are direct children to the currently progressing root level object. This method does have 2 disadvantages though:

  1. depending on the width and depth of the tree, it can give wildly wrong estimates;
  2. unbalanced trees (with nodes with significantly larger counts than other nodes) will have erratic progress bar behavior.

However, if you got any control over the object that the tree has (or can write extension methods), what you could do is write a recursive function that counts how many children the current item has, preferably something that's updated every time an item is added during the creation of the tree. The faster this method is, the better (using native properties is preferred over manual iteration), because it means you can use the answer suggested by @Bobwise.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.