summaryrefslogtreecommitdiff
path: root/progress.c
diff options
context:
space:
mode:
authorLibravatar Nicolas Pitre <nico@cam.org>2007-10-30 14:57:34 -0400
committerLibravatar Junio C Hamano <gitster@pobox.com>2007-10-30 16:08:40 -0700
commitcf84d51c43fa05cce416bfa3f5db3ad70773abdf (patch)
tree66174c02c7eb0d9cae466960a60467dd1e8fb297 /progress.c
parentrelax usage of the progress API (diff)
downloadtgif-cf84d51c43fa05cce416bfa3f5db3ad70773abdf.tar.xz
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 c548cf4ee0737a321ffe94f6a97c65baf87281be from Linus. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'progress.c')
-rw-r--r--progress.c80
1 files changed, 76 insertions, 4 deletions
diff --git a/progress.c b/progress.c
index c342e39c5d..15197fbe6c 100644
--- a/progress.c
+++ b/progress.c
@@ -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);
}