From c548cf4ee0737a321ffe94f6a97c65baf87281be Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 11 Feb 2006 10:43:56 -0800 Subject: [PATCH] Make "git clone" pack-fetching download statistics better Average it out over a few events to make the numbers stable, and fix the silly usec->binary-ms conversion. Yeah, yeah, it's arguably eye-candy to keep the user calm, but let's do that right. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- fetch-clone.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/fetch-clone.c b/fetch-clone.c index b67d97649..873312df3 100644 --- a/fetch-clone.c +++ b/fetch-clone.c @@ -130,12 +130,35 @@ int receive_unpack_pack(int fd[2], const char *me, int quiet) die("git-unpack-objects died of unnatural causes %d", status); } +/* + * We average out the download speed over this many "events", where + * an event is a minimum of about half a second. That way, we get + * a reasonably stable number. + */ +#define NR_AVERAGE (4) + +/* + * A "binary msec" is a power-of-two-msec, aka 1/1024th of a second. + * Keeing the time in that format means that "bytes / msecs" means + * is the same as kB/s (modulo rounding). + * + * 1000512 is a magic number (usecs in a second, rounded up by half + * of 1024, to make "rounding" come out right ;) + */ +#define usec_to_binarymsec(x) ((int)(x) / (1000512 >> 10)) + int receive_keep_pack(int fd[2], const char *me, int quiet) { char tmpfile[PATH_MAX]; int ofd, ifd; unsigned long total; static struct timeval prev_tv; + struct average { + unsigned long bytes; + unsigned long time; + } download[NR_AVERAGE] = { {0, 0}, }; + unsigned long avg_bytes, avg_time; + int idx = 0; ifd = fd[0]; snprintf(tmpfile, sizeof(tmpfile), @@ -146,6 +169,8 @@ int receive_keep_pack(int fd[2], const char *me, int quiet) gettimeofday(&prev_tv, NULL); total = 0; + avg_bytes = 0; + avg_time = 0; while (1) { char buf[8192]; ssize_t sz, wsz, pos; @@ -181,14 +206,27 @@ int receive_keep_pack(int fd[2], const char *me, int quiet) gettimeofday(&tv, NULL); msecs = tv.tv_sec - prev_tv.tv_sec; msecs <<= 10; - msecs += (int)(tv.tv_usec - prev_tv.tv_usec) >> 10; + msecs += usec_to_binarymsec(tv.tv_usec - prev_tv.tv_usec); + if (msecs > 500) { prev_tv = tv; last = total; - fprintf(stderr, "%4lu.%03luMB (%lu kB/s) \r", + + /* Update averages ..*/ + avg_bytes += diff; + avg_time += msecs; + avg_bytes -= download[idx].bytes; + avg_time -= download[idx].time; + download[idx].bytes = diff; + download[idx].time = msecs; + idx++; + if (idx >= NR_AVERAGE) + idx = 0; + + fprintf(stderr, "%4lu.%03luMB (%lu kB/s) \r", total >> 20, 1000*((total >> 10) & 1023)>>10, - diff / msecs ); + avg_bytes / avg_time ); } } } -- 2.30.2