From 42e18fbf5f94dd6bd303bf702e030a29fa39d6c4 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Oct 2007 21:55:45 -0400 Subject: more compact progress display Each progress can be on a single line instead of two. [sp: Changed "Checking files out" to "Checking out files" at Johannes Sixt's suggestion as it better explains the action that is taking place] Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- progress.c | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'progress.c') diff --git a/progress.c b/progress.c index 4344f4eed5..7629e0572b 100644 --- a/progress.c +++ b/progress.c @@ -35,10 +35,11 @@ static void clear_progress_signal(void) progress_update = 0; } -int display_progress(struct progress *progress, unsigned n) +static int display(struct progress *progress, unsigned n, int done) { + char *eol; + if (progress->delay) { - char buf[80]; if (!progress_update || --progress->delay) return 0; if (progress->total) { @@ -51,60 +52,56 @@ int display_progress(struct progress *progress, unsigned n) return 0; } } - if (snprintf(buf, sizeof(buf), - progress->delayed_title, progress->total)) - fprintf(stderr, "%s\n", buf); } + + progress->last_value = n; + 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%4u%% (%u/%u) done\r", - progress->prefix, percent, n, progress->total); + fprintf(stderr, "%s: %3u%% (%u/%u)%s", progress->title, + percent, n, progress->total, eol); progress_update = 0; - progress->need_lf = 1; return 1; } } else if (progress_update) { - fprintf(stderr, "%s%u\r", progress->prefix, n); + fprintf(stderr, "%s: %u%s", progress->title, n, eol); progress_update = 0; - progress->need_lf = 1; return 1; } + return 0; } -void start_progress(struct progress *progress, const char *title, - const char *prefix, unsigned total) +int display_progress(struct progress *progress, unsigned n) { - char buf[80]; - progress->prefix = prefix; - progress->total = total; - progress->last_percent = -1; - progress->delay = 0; - progress->need_lf = 0; - if (snprintf(buf, sizeof(buf), title, total)) - fprintf(stderr, "%s\n", buf); - set_progress_signal(); + return display(progress, n, 0); } void start_progress_delay(struct progress *progress, const char *title, - const char *prefix, unsigned total, - unsigned percent_treshold, unsigned delay) + unsigned total, unsigned percent_treshold, unsigned delay) { - progress->prefix = prefix; + progress->title = title; progress->total = total; + progress->last_value = -1; progress->last_percent = -1; progress->delayed_percent_treshold = percent_treshold; - progress->delayed_title = title; progress->delay = delay; - progress->need_lf = 0; set_progress_signal(); } +void start_progress(struct progress *progress, const char *title, unsigned total) +{ + start_progress_delay(progress, title, total, 0, 0); +} + void stop_progress(struct progress *progress) { + if (progress->last_value != -1) { + /* Force the last update */ + progress_update = 1; + display(progress, progress->last_value, 1); + } clear_progress_signal(); - if (progress->need_lf) - fputc('\n', stderr); } -- cgit v1.3 From dc6a0757c4f966dd124bd85be2adad5a0b7b2167 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 14:57:32 -0400 Subject: make struct progress an opaque type This allows for better management of progress "object" existence, as well as making the progress display implementation more independent from its callers. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 16 ++++++++-------- builtin-prune-packed.c | 7 +++---- builtin-unpack-objects.c | 6 +++--- index-pack.c | 12 ++++++------ progress.c | 33 +++++++++++++++++++++++++++------ progress.h | 18 +++++------------- unpack-trees.c | 10 +++++----- 7 files changed, 57 insertions(+), 45 deletions(-) (limited to 'progress.c') diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 21ba977df3..3ca5cc7800 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -73,7 +73,7 @@ static int depth = 50; static int delta_search_threads = 1; static int pack_to_stdout; static int num_preferred_base; -static struct progress progress_state; +static struct progress *progress_state; static int pack_compression_level = Z_DEFAULT_COMPRESSION; static int pack_compression_seen; @@ -598,7 +598,7 @@ static void write_pack_file(void) uint32_t nr_remaining = nr_result; if (do_progress) - start_progress(&progress_state, "Writing objects", nr_result); + progress_state = start_progress("Writing objects", nr_result); written_list = xmalloc(nr_objects * sizeof(struct object_entry *)); do { @@ -630,7 +630,7 @@ static void write_pack_file(void) break; offset = offset_one; if (do_progress) - display_progress(&progress_state, written); + display_progress(progress_state, written); } /* @@ -854,7 +854,7 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, object_ix[-1 - ix] = nr_objects; if (progress) - display_progress(&progress_state, nr_objects); + display_progress(progress_state, nr_objects); if (name && no_try_delta(name)) entry->no_try_delta = 1; @@ -1518,7 +1518,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size, progress_lock(); (*processed)++; if (progress) - display_progress(&progress_state, *processed); + display_progress(progress_state, *processed); progress_unlock(); /* @@ -1718,8 +1718,8 @@ static void prepare_pack(int window, int depth) if (nr_deltas && n > 1) { unsigned nr_done = 0; if (progress) - start_progress(&progress_state, "Compressing objects", - nr_deltas); + progress_state = start_progress("Compressing objects", + nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); if (progress) @@ -2135,7 +2135,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) prepare_packed_git(); if (progress) - start_progress(&progress_state, "Counting objects", 0); + progress_state = start_progress("Counting objects", 0); if (!use_internal_rev_list) read_object_list_from_stdin(); else { diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index 907e36828f..c66fb037f6 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -8,7 +8,7 @@ static const char prune_packed_usage[] = #define DRY_RUN 01 #define VERBOSE 02 -static struct progress progress; +static struct progress *progress; static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) { @@ -16,7 +16,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) char hex[40]; if (opts == VERBOSE) - display_progress(&progress, i + 1); + display_progress(progress, i + 1); sprintf(hex, "%02x", i); while ((de = readdir(dir)) != NULL) { @@ -46,8 +46,7 @@ void prune_packed_objects(int opts) int len = strlen(dir); if (opts == VERBOSE) - start_progress_delay(&progress, - "Removing duplicate objects", + progress = start_progress_delay("Removing duplicate objects", 256, 95, 2); if (len > PATH_MAX - 42) diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 2317b8f411..e0ecbc51a7 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -311,7 +311,7 @@ static void unpack_one(unsigned nr) static void unpack_all(void) { int i; - struct progress progress; + struct progress *progress = NULL; struct pack_header *hdr = fill(sizeof(struct pack_header)); unsigned nr_objects = ntohl(hdr->hdr_entries); @@ -322,12 +322,12 @@ static void unpack_all(void) use(sizeof(struct pack_header)); if (!quiet) - start_progress(&progress, "Unpacking objects", nr_objects); + progress = start_progress("Unpacking objects", nr_objects); obj_list = xmalloc(nr_objects * sizeof(*obj_list)); for (i = 0; i < nr_objects; i++) { unpack_one(i); if (!quiet) - display_progress(&progress, i + 1); + display_progress(progress, i + 1); } if (!quiet) stop_progress(&progress); diff --git a/index-pack.c b/index-pack.c index 2f149a40fd..b4543a4cc2 100644 --- a/index-pack.c +++ b/index-pack.c @@ -46,7 +46,7 @@ static int nr_resolved_deltas; static int from_stdin; static int verbose; -static struct progress progress; +static struct progress *progress; /* We always read in 4kB chunks. */ static unsigned char input_buffer[4096]; @@ -406,7 +406,7 @@ static void parse_pack_objects(unsigned char *sha1) * - remember base (SHA1 or offset) for all deltas. */ if (verbose) - start_progress(&progress, "Indexing objects", nr_objects); + progress = start_progress("Indexing objects", nr_objects); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; data = unpack_raw_entry(obj, &delta->base); @@ -419,7 +419,7 @@ static void parse_pack_objects(unsigned char *sha1) sha1_object(data, obj->size, obj->type, obj->idx.sha1); free(data); if (verbose) - display_progress(&progress, i+1); + display_progress(progress, i+1); } objects[i].idx.offset = consumed_bytes; if (verbose) @@ -455,7 +455,7 @@ static void parse_pack_objects(unsigned char *sha1) * for some more deltas. */ if (verbose) - start_progress(&progress, "Resolving deltas", nr_deltas); + progress = start_progress("Resolving deltas", nr_deltas); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; union delta_base base; @@ -487,7 +487,7 @@ static void parse_pack_objects(unsigned char *sha1) } free(data); if (verbose) - display_progress(&progress, nr_resolved_deltas); + display_progress(progress, nr_resolved_deltas); } } @@ -595,7 +595,7 @@ static void fix_unresolved_deltas(int nr_unresolved) append_obj_to_pack(d->base.sha1, data, size, type); free(data); if (verbose) - display_progress(&progress, nr_resolved_deltas); + display_progress(progress, nr_resolved_deltas); } free(sorted_by_pos); } diff --git a/progress.c b/progress.c index 7629e0572b..c342e39c5d 100644 --- a/progress.c +++ b/progress.c @@ -1,6 +1,15 @@ #include "git-compat-util.h" #include "progress.h" +struct progress { + const char *title; + int last_value; + unsigned total; + unsigned last_percent; + unsigned delay; + unsigned delayed_percent_treshold; +}; + static volatile sig_atomic_t progress_update; static void progress_interval(int signum) @@ -76,12 +85,18 @@ static int display(struct progress *progress, unsigned n, int done) int display_progress(struct progress *progress, unsigned n) { - return display(progress, n, 0); + return progress ? display(progress, n, 0) : 0; } -void start_progress_delay(struct progress *progress, const char *title, - unsigned total, unsigned percent_treshold, unsigned delay) +struct progress *start_progress_delay(const char *title, unsigned total, + unsigned percent_treshold, unsigned delay) { + struct progress *progress = malloc(sizeof(*progress)); + if (!progress) { + /* unlikely, but here's a good fallback */ + fprintf(stderr, "%s...\n", title); + return NULL; + } progress->title = title; progress->total = total; progress->last_value = -1; @@ -89,19 +104,25 @@ void start_progress_delay(struct progress *progress, const char *title, progress->delayed_percent_treshold = percent_treshold; progress->delay = delay; set_progress_signal(); + return progress; } -void start_progress(struct progress *progress, const char *title, unsigned total) +struct progress *start_progress(const char *title, unsigned total) { - start_progress_delay(progress, title, total, 0, 0); + return start_progress_delay(title, total, 0, 0); } -void stop_progress(struct progress *progress) +void stop_progress(struct progress **p_progress) { + struct progress *progress = *p_progress; + if (!progress) + return; + *p_progress = NULL; if (progress->last_value != -1) { /* Force the last update */ progress_update = 1; display(progress, progress->last_value, 1); } clear_progress_signal(); + free(progress); } diff --git a/progress.h b/progress.h index 07b56bdbb5..4c6d53524b 100644 --- a/progress.h +++ b/progress.h @@ -1,20 +1,12 @@ #ifndef PROGRESS_H #define PROGRESS_H -struct progress { - const char *title; - int last_value; - unsigned total; - unsigned last_percent; - unsigned delay; - unsigned delayed_percent_treshold; -}; +struct progress; int display_progress(struct progress *progress, unsigned n); -void start_progress(struct progress *progress, const char *title, - unsigned total); -void start_progress_delay(struct progress *progress, const char *title, - unsigned total, unsigned percent_treshold, unsigned delay); -void stop_progress(struct progress *progress); +struct progress *start_progress(const char *title, unsigned total); +struct progress *start_progress_delay(const char *title, unsigned total, + unsigned percent_treshold, unsigned delay); +void stop_progress(struct progress **progress); #endif diff --git a/unpack-trees.c b/unpack-trees.c index 32251018b2..6776c29cde 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -297,7 +297,7 @@ static void check_updates(struct cache_entry **src, int nr, { unsigned short mask = htons(CE_UPDATE); unsigned cnt = 0, total = 0; - struct progress progress; + struct progress *progress = NULL; char last_symlink[PATH_MAX]; if (o->update && o->verbose_update) { @@ -307,8 +307,8 @@ static void check_updates(struct cache_entry **src, int nr, total++; } - start_progress_delay(&progress, "Checking out files", - total, 50, 2); + progress = start_progress_delay("Checking out files", + total, 50, 2); cnt = 0; } @@ -318,7 +318,7 @@ static void check_updates(struct cache_entry **src, int nr, if (total) if (!ce->ce_mode || ce->ce_flags & mask) - display_progress(&progress, ++cnt); + display_progress(progress, ++cnt); if (!ce->ce_mode) { if (o->update) unlink_entry(ce->name, last_symlink); @@ -333,7 +333,7 @@ static void check_updates(struct cache_entry **src, int nr, } } if (total) - stop_progress(&progress);; + stop_progress(&progress); } int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o) -- cgit v1.3 From cf84d51c43fa05cce416bfa3f5db3ad70773abdf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 14:57:34 -0400 Subject: 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 Signed-off-by: Junio C Hamano --- progress.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- progress.h | 1 + 2 files changed, 77 insertions(+), 4 deletions(-) (limited to 'progress.c') 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); } diff --git a/progress.h b/progress.h index 4c6d53524b..61cb68dfa5 100644 --- a/progress.h +++ b/progress.h @@ -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, -- cgit v1.3 From 74b6792f7b2d4b410459cf96977a2007ddea8675 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 15:41:13 -0400 Subject: add some copyright notice to the progress display code Some self patting on the back to keep my ego alive. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'progress.c') diff --git a/progress.c b/progress.c index 15197fbe6c..34a59611fb 100644 --- a/progress.c +++ b/progress.c @@ -1,3 +1,13 @@ +/* + * Simple text-based progress display module for GIT + * + * Copyright (c) 2007 by Nicolas Pitre + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + #include "git-compat-util.h" #include "progress.h" -- cgit v1.3 From 3e935d19822db08cc0dedd8764135771ffd6ec7b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 1 Nov 2007 16:59:56 -0400 Subject: make sure throughput display gets updated even if progress doesn't move Currently the progress/throughput display update happens only through display_progress(). If the progress based on object count remains unchanged because a large object is being received, the latest throughput won't be displayed. The display update should occur through display_throughput() as well. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'progress.c') diff --git a/progress.c b/progress.c index 34a59611fb..39d5d2c9f2 100644 --- a/progress.c +++ b/progress.c @@ -160,6 +160,9 @@ void display_throughput(struct progress *progress, unsigned long n) tp->last_misecs[tp->idx] = misecs; tp->idx = (tp->idx + 1) % TP_IDX_MAX; tp->count = 0; + + if (progress->last_value != -1 && progress_update) + display(progress, progress->last_value, 0); } } -- cgit v1.3 From 81f6654a47075a345ba63a394921f77fc87b6500 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 1 Nov 2007 16:59:57 -0400 Subject: Show total transferred as part of throughput progress Right now it is infeasible to offer to the user a reasonable concept of when a clone will be complete as we aren't able to come up with the final pack size until after we have actually transferred the entire thing to the client. However in many cases users can work with a rough rule-of-thumb; for example it is somewhat well known that git.git is about 16 MiB today and that linux-2.6.git is over 120 MiB. We now show the total amount of data we have transferred over the network as part of the throughput meter, organizing it in "human friendly" terms like `ls -h` would do. Users can glance at this, see that the total transferred size is about 3 MiB, see the throughput of X KiB/sec, and determine a reasonable figure of about when the clone will be complete, assuming they know the rough size of the source repository or are able to obtain it. This is also a helpful indicator that there is progress being made even if we stall on a very large object. The thoughput meter may remain relatively constant and the percentage complete and object count won't be changing, but the total transferred will be increasing as additional data is received for this object. [from an initial proposal from Shawn O. Pearce] Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'progress.c') diff --git a/progress.c b/progress.c index 39d5d2c9f2..3f6a602a53 100644 --- a/progress.c +++ b/progress.c @@ -15,13 +15,14 @@ struct throughput { struct timeval prev_tv; + off_t total; 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]; + char display[32]; }; struct progress { @@ -128,6 +129,7 @@ void display_throughput(struct progress *progress, unsigned long n) return; } + tp->total += n; tp->count += n; /* @@ -149,11 +151,32 @@ void display_throughput(struct progress *progress, unsigned long n) misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977; if (misecs > 512) { + int l = sizeof(tp->display); 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); + + if (tp->total > 1 << 30) { + l -= snprintf(tp->display, l, ", %u.%2.2u GiB", + (int)(tp->total >> 30), + (int)(tp->total & ((1 << 30) - 1)) / 10737419); + } else if (tp->total > 1 << 20) { + l -= snprintf(tp->display, l, ", %u.%2.2u MiB", + (int)(tp->total >> 20), + ((int)(tp->total & ((1 << 20) - 1)) + * 100) >> 20); + } else if (tp->total > 1 << 10) { + l -= snprintf(tp->display, l, ", %u.%2.2u KiB", + (int)(tp->total >> 10), + ((int)(tp->total & ((1 << 10) - 1)) + * 100) >> 10); + } else { + l -= snprintf(tp->display, l, ", %u bytes", + (int)tp->total); + } + snprintf(tp->display + sizeof(tp->display) - l, l, + " | %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; -- cgit v1.3