11#include "git-compat-util.h"
22#include "progress.h"
33
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+
417struct progress {
518 const char * title ;
619 int last_value ;
720 unsigned total ;
821 unsigned last_percent ;
922 unsigned delay ;
1023 unsigned delayed_percent_treshold ;
24+ struct throughput * throughput ;
1125};
1226
1327static volatile sig_atomic_t progress_update ;
@@ -46,7 +60,7 @@ static void clear_progress_signal(void)
4660
4761static int display (struct progress * progress , unsigned n , int done )
4862{
49- char * eol ;
63+ char * eol , * tp ;
5064
5165 if (progress -> delay ) {
5266 if (!progress_update || -- progress -> delay )
@@ -64,25 +78,81 @@ static int display(struct progress *progress, unsigned n, int done)
6478 }
6579
6680 progress -> last_value = n ;
81+ tp = (progress -> throughput ) ? progress -> throughput -> display : "" ;
6782 eol = done ? ", done. \n" : " \r" ;
6883 if (progress -> total ) {
6984 unsigned percent = n * 100 / progress -> total ;
7085 if (percent != progress -> last_percent || progress_update ) {
7186 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 );
7490 progress_update = 0 ;
7591 return 1 ;
7692 }
7793 } 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 );
7995 progress_update = 0 ;
8096 return 1 ;
8197 }
8298
8399 return 0 ;
84100}
85101
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+
86156int display_progress (struct progress * progress , unsigned n )
87157{
88158 return progress ? display (progress , n , 0 ) : 0 ;
@@ -103,6 +173,7 @@ struct progress *start_progress_delay(const char *title, unsigned total,
103173 progress -> last_percent = -1 ;
104174 progress -> delayed_percent_treshold = percent_treshold ;
105175 progress -> delay = delay ;
176+ progress -> throughput = NULL ;
106177 set_progress_signal ();
107178 return progress ;
108179}
@@ -124,5 +195,6 @@ void stop_progress(struct progress **p_progress)
124195 display (progress , progress -> last_value , 1 );
125196 }
126197 clear_progress_signal ();
198+ free (progress -> throughput );
127199 free (progress );
128200}
0 commit comments