|
12 | 12 | #include "gettext.h"
|
13 | 13 | #include "progress.h"
|
14 | 14 | #include "strbuf.h"
|
| 15 | +#include "trace.h" |
15 | 16 |
|
16 | 17 | #define TP_IDX_MAX 8
|
17 | 18 |
|
18 | 19 | struct throughput {
|
19 | 20 | off_t curr_total;
|
20 | 21 | off_t prev_total;
|
21 |
| - struct timeval prev_tv; |
| 22 | + uint64_t prev_ns; |
22 | 23 | unsigned int avg_bytes;
|
23 | 24 | unsigned int avg_misecs;
|
24 | 25 | unsigned int last_bytes[TP_IDX_MAX];
|
@@ -127,65 +128,65 @@ static void throughput_string(struct strbuf *buf, off_t total,
|
127 | 128 | void display_throughput(struct progress *progress, off_t total)
|
128 | 129 | {
|
129 | 130 | struct throughput *tp;
|
130 |
| - struct timeval tv; |
131 |
| - unsigned int misecs; |
| 131 | + uint64_t now_ns; |
| 132 | + unsigned int misecs, count, rate; |
| 133 | + struct strbuf buf = STRBUF_INIT; |
132 | 134 |
|
133 | 135 | if (!progress)
|
134 | 136 | return;
|
135 | 137 | tp = progress->throughput;
|
136 | 138 |
|
137 |
| - gettimeofday(&tv, NULL); |
| 139 | + now_ns = getnanotime(); |
138 | 140 |
|
139 | 141 | if (!tp) {
|
140 | 142 | progress->throughput = tp = calloc(1, sizeof(*tp));
|
141 | 143 | if (tp) {
|
142 | 144 | tp->prev_total = tp->curr_total = total;
|
143 |
| - tp->prev_tv = tv; |
| 145 | + tp->prev_ns = now_ns; |
144 | 146 | }
|
145 | 147 | return;
|
146 | 148 | }
|
147 | 149 | tp->curr_total = total;
|
148 | 150 |
|
| 151 | + /* only update throughput every 0.5 s */ |
| 152 | + if (now_ns - tp->prev_ns <= 500000000) |
| 153 | + return; |
| 154 | + |
149 | 155 | /*
|
150 |
| - * We have x = bytes and y = microsecs. We want z = KiB/s: |
| 156 | + * We have x = bytes and y = nanosecs. We want z = KiB/s: |
151 | 157 | *
|
152 |
| - * z = (x / 1024) / (y / 1000000) |
153 |
| - * z = x / y * 1000000 / 1024 |
154 |
| - * z = x / (y * 1024 / 1000000) |
| 158 | + * z = (x / 1024) / (y / 1000000000) |
| 159 | + * z = x / y * 1000000000 / 1024 |
| 160 | + * z = x / (y * 1024 / 1000000000) |
155 | 161 | * z = x / y'
|
156 | 162 | *
|
157 | 163 | * To simplify things we'll keep track of misecs, or 1024th of a sec
|
158 | 164 | * obtained with:
|
159 | 165 | *
|
160 |
| - * y' = y * 1024 / 1000000 |
161 |
| - * y' = y / (1000000 / 1024) |
162 |
| - * y' = y / 977 |
| 166 | + * y' = y * 1024 / 1000000000 |
| 167 | + * y' = y * (2^10 / 2^42) * (2^42 / 1000000000) |
| 168 | + * y' = y / 2^32 * 4398 |
| 169 | + * y' = (y * 4398) >> 32 |
163 | 170 | */
|
164 |
| - misecs = (tv.tv_sec - tp->prev_tv.tv_sec) * 1024; |
165 |
| - misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977; |
| 171 | + misecs = ((now_ns - tp->prev_ns) * 4398) >> 32; |
166 | 172 |
|
167 |
| - if (misecs > 512) { |
168 |
| - struct strbuf buf = STRBUF_INIT; |
169 |
| - unsigned int count, rate; |
| 173 | + count = total - tp->prev_total; |
| 174 | + tp->prev_total = total; |
| 175 | + tp->prev_ns = now_ns; |
| 176 | + tp->avg_bytes += count; |
| 177 | + tp->avg_misecs += misecs; |
| 178 | + rate = tp->avg_bytes / tp->avg_misecs; |
| 179 | + tp->avg_bytes -= tp->last_bytes[tp->idx]; |
| 180 | + tp->avg_misecs -= tp->last_misecs[tp->idx]; |
| 181 | + tp->last_bytes[tp->idx] = count; |
| 182 | + tp->last_misecs[tp->idx] = misecs; |
| 183 | + tp->idx = (tp->idx + 1) % TP_IDX_MAX; |
170 | 184 |
|
171 |
| - count = total - tp->prev_total; |
172 |
| - tp->prev_total = total; |
173 |
| - tp->prev_tv = tv; |
174 |
| - tp->avg_bytes += count; |
175 |
| - tp->avg_misecs += misecs; |
176 |
| - rate = tp->avg_bytes / tp->avg_misecs; |
177 |
| - tp->avg_bytes -= tp->last_bytes[tp->idx]; |
178 |
| - tp->avg_misecs -= tp->last_misecs[tp->idx]; |
179 |
| - tp->last_bytes[tp->idx] = count; |
180 |
| - tp->last_misecs[tp->idx] = misecs; |
181 |
| - tp->idx = (tp->idx + 1) % TP_IDX_MAX; |
182 |
| - |
183 |
| - throughput_string(&buf, total, rate); |
184 |
| - strncpy(tp->display, buf.buf, sizeof(tp->display)); |
185 |
| - strbuf_release(&buf); |
186 |
| - if (progress->last_value != -1 && progress_update) |
187 |
| - display(progress, progress->last_value, NULL); |
188 |
| - } |
| 185 | + throughput_string(&buf, total, rate); |
| 186 | + strncpy(tp->display, buf.buf, sizeof(tp->display)); |
| 187 | + strbuf_release(&buf); |
| 188 | + if (progress->last_value != -1 && progress_update) |
| 189 | + display(progress, progress->last_value, NULL); |
189 | 190 | }
|
190 | 191 |
|
191 | 192 | int display_progress(struct progress *progress, unsigned n)
|
|
0 commit comments