add throughput to progress display

This adds the ability for the progress code to also display transfer
throughput when that makes sense.

The math was inspired by commit c548cf4ee0
from Linus.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
pull/288/head
Nicolas Pitre 15 years ago committed by Junio C Hamano
parent 4d4fcc5451
commit cf84d51c43
  1. 80
      progress.c
  2. 1
      progress.h

@ -1,6 +1,19 @@
#include "git-compat-util.h"
#include "progress.h"
#define TP_IDX_MAX 8
struct throughput {
struct timeval prev_tv;
unsigned long count;
unsigned long avg_bytes;
unsigned long last_bytes[TP_IDX_MAX];
unsigned int avg_misecs;
unsigned int last_misecs[TP_IDX_MAX];
unsigned int idx;
char display[20];
};
struct progress {
const char *title;
int last_value;
@ -8,6 +21,7 @@ struct progress {
unsigned last_percent;
unsigned delay;
unsigned delayed_percent_treshold;
struct throughput *throughput;
};
static volatile sig_atomic_t progress_update;
@ -46,7 +60,7 @@ static void clear_progress_signal(void)
static int display(struct progress *progress, unsigned n, int done)
{
char *eol;
char *eol, *tp;
if (progress->delay) {
if (!progress_update || --progress->delay)
@ -64,18 +78,20 @@ static int display(struct progress *progress, unsigned n, int done)
}
progress->last_value = n;
tp = (progress->throughput) ? progress->throughput->display : "";
eol = done ? ", done. \n" : " \r";
if (progress->total) {
unsigned percent = n * 100 / progress->total;
if (percent != progress->last_percent || progress_update) {
progress->last_percent = percent;
fprintf(stderr, "%s: %3u%% (%u/%u)%s", progress->title,
percent, n, progress->total, eol);
fprintf(stderr, "%s: %3u%% (%u/%u)%s%s",
progress->title, percent, n,
progress->total, tp, eol);
progress_update = 0;
return 1;
}
} else if (progress_update) {
fprintf(stderr, "%s: %u%s", progress->title, n, eol);
fprintf(stderr, "%s: %u%s%s", progress->title, n, tp, eol);
progress_update = 0;
return 1;
}
@ -83,6 +99,60 @@ static int display(struct progress *progress, unsigned n, int done)
return 0;
}
void display_throughput(struct progress *progress, unsigned long n)
{
struct throughput *tp;
struct timeval tv;
unsigned int misecs;
if (!progress)
return;
tp = progress->throughput;
gettimeofday(&tv, NULL);
if (!tp) {
progress->throughput = tp = calloc(1, sizeof(*tp));
if (tp)
tp->prev_tv = tv;
return;
}
tp->count += n;
/*
* We have x = bytes and y = microsecs. We want z = KiB/s:
*
* z = (x / 1024) / (y / 1000000)
* z = x / y * 1000000 / 1024
* z = x / (y * 1024 / 1000000)
* z = x / y'
*
* To simplify things we'll keep track of misecs, or 1024th of a sec
* obtained with:
*
* y' = y * 1024 / 1000000
* y' = y / (1000000 / 1024)
* y' = y / 977
*/
misecs = (tv.tv_sec - tp->prev_tv.tv_sec) * 1024;
misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977;
if (misecs > 512) {
tp->prev_tv = tv;
tp->avg_bytes += tp->count;
tp->avg_misecs += misecs;
snprintf(tp->display, sizeof(tp->display),
", %lu KiB/s", tp->avg_bytes / tp->avg_misecs);
tp->avg_bytes -= tp->last_bytes[tp->idx];
tp->avg_misecs -= tp->last_misecs[tp->idx];
tp->last_bytes[tp->idx] = tp->count;
tp->last_misecs[tp->idx] = misecs;
tp->idx = (tp->idx + 1) % TP_IDX_MAX;
tp->count = 0;
}
}
int display_progress(struct progress *progress, unsigned n)
{
return progress ? display(progress, n, 0) : 0;
@ -103,6 +173,7 @@ struct progress *start_progress_delay(const char *title, unsigned total,
progress->last_percent = -1;
progress->delayed_percent_treshold = percent_treshold;
progress->delay = delay;
progress->throughput = NULL;
set_progress_signal();
return progress;
}
@ -124,5 +195,6 @@ void stop_progress(struct progress **p_progress)
display(progress, progress->last_value, 1);
}
clear_progress_signal();
free(progress->throughput);
free(progress);
}

@ -3,6 +3,7 @@
struct progress;
void display_throughput(struct progress *progress, unsigned long n);
int display_progress(struct progress *progress, unsigned n);
struct progress *start_progress(const char *title, unsigned total);
struct progress *start_progress_delay(const char *title, unsigned total,

Loading…
Cancel
Save