progress: add sparse mode to force 100% complete message

Add new start_sparse_progress() and start_delayed_sparse_progress()
constructors and "sparse" flag to struct progress.

Teach stop_progress() to force a 100% complete progress message before
printing the final "done" message when "sparse" is set.

Calling display_progress() for every item in a large set can
be expensive.  If callers try to filter this for performance
reasons, such as emitting every k-th item, progress would
not reach 100% unless they made a final call to display_progress()
with the item count before calling stop_progress().

Now this is automatic when "sparse" is set.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff Hostetler 2019-03-21 12:36:11 -07:00 committed by Junio C Hamano
parent 041f5ea1cf
commit 9d81ecb52b
2 changed files with 38 additions and 3 deletions

View File

@ -34,6 +34,7 @@ struct progress {
uint64_t total; uint64_t total;
unsigned last_percent; unsigned last_percent;
unsigned delay; unsigned delay;
unsigned sparse;
struct throughput *throughput; struct throughput *throughput;
uint64_t start_ns; uint64_t start_ns;
}; };
@ -194,7 +195,7 @@ int display_progress(struct progress *progress, uint64_t n)
} }
static struct progress *start_progress_delay(const char *title, uint64_t total, static struct progress *start_progress_delay(const char *title, uint64_t total,
unsigned delay) unsigned delay, unsigned sparse)
{ {
struct progress *progress = malloc(sizeof(*progress)); struct progress *progress = malloc(sizeof(*progress));
if (!progress) { if (!progress) {
@ -208,6 +209,7 @@ static struct progress *start_progress_delay(const char *title, uint64_t total,
progress->last_value = -1; progress->last_value = -1;
progress->last_percent = -1; progress->last_percent = -1;
progress->delay = delay; progress->delay = delay;
progress->sparse = sparse;
progress->throughput = NULL; progress->throughput = NULL;
progress->start_ns = getnanotime(); progress->start_ns = getnanotime();
set_progress_signal(); set_progress_signal();
@ -216,16 +218,46 @@ static struct progress *start_progress_delay(const char *title, uint64_t total,
struct progress *start_delayed_progress(const char *title, uint64_t total) struct progress *start_delayed_progress(const char *title, uint64_t total)
{ {
return start_progress_delay(title, total, 2); return start_progress_delay(title, total, 2, 0);
} }
struct progress *start_progress(const char *title, uint64_t total) struct progress *start_progress(const char *title, uint64_t total)
{ {
return start_progress_delay(title, total, 0); return start_progress_delay(title, total, 0, 0);
}
/*
* Here "sparse" means that the caller might use some sampling criteria to
* decide when to call display_progress() rather than calling it for every
* integer value in[0 .. total). In particular, the caller might not call
* display_progress() for the last value in the range.
*
* When "sparse" is set, stop_progress() will automatically force the done
* message to show 100%.
*/
struct progress *start_sparse_progress(const char *title, uint64_t total)
{
return start_progress_delay(title, total, 0, 1);
}
struct progress *start_delayed_sparse_progress(const char *title,
uint64_t total)
{
return start_progress_delay(title, total, 2, 1);
}
static void finish_if_sparse(struct progress *progress)
{
if (progress &&
progress->sparse &&
progress->last_value != progress->total)
display_progress(progress, progress->total);
} }
void stop_progress(struct progress **p_progress) void stop_progress(struct progress **p_progress)
{ {
finish_if_sparse(*p_progress);
stop_progress_msg(p_progress, _("done")); stop_progress_msg(p_progress, _("done"));
} }

View File

@ -6,7 +6,10 @@ struct progress;
void display_throughput(struct progress *progress, uint64_t total); void display_throughput(struct progress *progress, uint64_t total);
int display_progress(struct progress *progress, uint64_t n); int display_progress(struct progress *progress, uint64_t n);
struct progress *start_progress(const char *title, uint64_t total); struct progress *start_progress(const char *title, uint64_t total);
struct progress *start_sparse_progress(const char *title, uint64_t total);
struct progress *start_delayed_progress(const char *title, uint64_t total); struct progress *start_delayed_progress(const char *title, uint64_t total);
struct progress *start_delayed_sparse_progress(const char *title,
uint64_t total);
void stop_progress(struct progress **progress); void stop_progress(struct progress **progress);
void stop_progress_msg(struct progress **progress, const char *msg); void stop_progress_msg(struct progress **progress, const char *msg);