1
1
#include "git-compat-util.h"
2
2
#include "progress.h"
3
3
4
+ #define TP_IDX_MAX 8
5
+
6
+ struct throughput {
7
+ struct timeval prev_tv ;
8
+ unsigned long count ;
9
+ unsigned long avg_bytes ;
10
+ unsigned long last_bytes [TP_IDX_MAX ];
11
+ unsigned int avg_misecs ;
12
+ unsigned int last_misecs [TP_IDX_MAX ];
13
+ unsigned int idx ;
14
+ char display [20 ];
15
+ };
16
+
4
17
struct progress {
5
18
const char * title ;
6
19
int last_value ;
7
20
unsigned total ;
8
21
unsigned last_percent ;
9
22
unsigned delay ;
10
23
unsigned delayed_percent_treshold ;
24
+ struct throughput * throughput ;
11
25
};
12
26
13
27
static volatile sig_atomic_t progress_update ;
@@ -46,7 +60,7 @@ static void clear_progress_signal(void)
46
60
47
61
static int display (struct progress * progress , unsigned n , int done )
48
62
{
49
- char * eol ;
63
+ char * eol , * tp ;
50
64
51
65
if (progress -> delay ) {
52
66
if (!progress_update || -- progress -> delay )
@@ -64,25 +78,81 @@ static int display(struct progress *progress, unsigned n, int done)
64
78
}
65
79
66
80
progress -> last_value = n ;
81
+ tp = (progress -> throughput ) ? progress -> throughput -> display : "" ;
67
82
eol = done ? ", done. \n" : " \r" ;
68
83
if (progress -> total ) {
69
84
unsigned percent = n * 100 / progress -> total ;
70
85
if (percent != progress -> last_percent || progress_update ) {
71
86
progress -> last_percent = percent ;
72
- fprintf (stderr , "%s: %3u%% (%u/%u)%s" , progress -> title ,
73
- percent , n , progress -> total , eol );
87
+ fprintf (stderr , "%s: %3u%% (%u/%u)%s%s" ,
88
+ progress -> title , percent , n ,
89
+ progress -> total , tp , eol );
74
90
progress_update = 0 ;
75
91
return 1 ;
76
92
}
77
93
} else if (progress_update ) {
78
- fprintf (stderr , "%s: %u%s" , progress -> title , n , eol );
94
+ fprintf (stderr , "%s: %u%s%s " , progress -> title , n , tp , eol );
79
95
progress_update = 0 ;
80
96
return 1 ;
81
97
}
82
98
83
99
return 0 ;
84
100
}
85
101
102
+ void display_throughput (struct progress * progress , unsigned long n )
103
+ {
104
+ struct throughput * tp ;
105
+ struct timeval tv ;
106
+ unsigned int misecs ;
107
+
108
+ if (!progress )
109
+ return ;
110
+ tp = progress -> throughput ;
111
+
112
+ gettimeofday (& tv , NULL );
113
+
114
+ if (!tp ) {
115
+ progress -> throughput = tp = calloc (1 , sizeof (* tp ));
116
+ if (tp )
117
+ tp -> prev_tv = tv ;
118
+ return ;
119
+ }
120
+
121
+ tp -> count += n ;
122
+
123
+ /*
124
+ * We have x = bytes and y = microsecs. We want z = KiB/s:
125
+ *
126
+ * z = (x / 1024) / (y / 1000000)
127
+ * z = x / y * 1000000 / 1024
128
+ * z = x / (y * 1024 / 1000000)
129
+ * z = x / y'
130
+ *
131
+ * To simplify things we'll keep track of misecs, or 1024th of a sec
132
+ * obtained with:
133
+ *
134
+ * y' = y * 1024 / 1000000
135
+ * y' = y / (1000000 / 1024)
136
+ * y' = y / 977
137
+ */
138
+ misecs = (tv .tv_sec - tp -> prev_tv .tv_sec ) * 1024 ;
139
+ misecs += (int )(tv .tv_usec - tp -> prev_tv .tv_usec ) / 977 ;
140
+
141
+ if (misecs > 512 ) {
142
+ tp -> prev_tv = tv ;
143
+ tp -> avg_bytes += tp -> count ;
144
+ tp -> avg_misecs += misecs ;
145
+ snprintf (tp -> display , sizeof (tp -> display ),
146
+ ", %lu KiB/s" , tp -> avg_bytes / tp -> avg_misecs );
147
+ tp -> avg_bytes -= tp -> last_bytes [tp -> idx ];
148
+ tp -> avg_misecs -= tp -> last_misecs [tp -> idx ];
149
+ tp -> last_bytes [tp -> idx ] = tp -> count ;
150
+ tp -> last_misecs [tp -> idx ] = misecs ;
151
+ tp -> idx = (tp -> idx + 1 ) % TP_IDX_MAX ;
152
+ tp -> count = 0 ;
153
+ }
154
+ }
155
+
86
156
int display_progress (struct progress * progress , unsigned n )
87
157
{
88
158
return progress ? display (progress , n , 0 ) : 0 ;
@@ -103,6 +173,7 @@ struct progress *start_progress_delay(const char *title, unsigned total,
103
173
progress -> last_percent = -1 ;
104
174
progress -> delayed_percent_treshold = percent_treshold ;
105
175
progress -> delay = delay ;
176
+ progress -> throughput = NULL ;
106
177
set_progress_signal ();
107
178
return progress ;
108
179
}
@@ -124,5 +195,6 @@ void stop_progress(struct progress **p_progress)
124
195
display (progress , progress -> last_value , 1 );
125
196
}
126
197
clear_progress_signal ();
198
+ free (progress -> throughput );
127
199
free (progress );
128
200
}
0 commit comments