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>
This commit is contained in:
Nicolas Pitre 2007-10-30 14:57:34 -04:00 коммит произвёл Junio C Hamano
Родитель 4d4fcc5451
Коммит cf84d51c43
2 изменённых файлов: 77 добавлений и 4 удалений

Просмотреть файл

@ -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,