Skip to content

Commit

Permalink
add throughput to progress display
Browse files Browse the repository at this point in the history
This adds the ability for the progress code to also display transfer
throughput when that makes sense.

The math was inspired by commit c548cf4
from Linus.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Nicolas Pitre authored and Junio C Hamano committed Oct 30, 2007
1 parent 4d4fcc5 commit cf84d51
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 4 deletions.
80 changes: 76 additions & 4 deletions progress.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
#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;
unsigned total;
unsigned last_percent;
unsigned delay;
unsigned delayed_percent_treshold;
struct throughput *throughput;
};

static volatile sig_atomic_t progress_update;
Expand Down Expand Up @@ -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)
Expand All @@ -64,25 +78,81 @@ 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;
}

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;
Expand All @@ -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;
}
Expand All @@ -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);
}
1 change: 1 addition & 0 deletions progress.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit cf84d51

Please sign in to comment.