Mercurial > hg
comparison mercurial/progress.py @ 34314:a667f0ca1d5f
progress: make ETA only consider progress made in the last minute
This patch limits the estimate time interval to roughly the last minute
(configurable by `estimateinterval`) to be more practical. See the test
change for why this is better.
.. feature:: Estimated time is more accurate with non-linear progress
Differential Revision: https://phab.mercurial-scm.org/D820
author | Jun Wu <quark@fb.com> |
---|---|
date | Wed, 27 Sep 2017 15:14:59 -0700 |
parents | f428c347d32b |
children | a57c938e7ac8 |
comparison
equal
deleted
inserted
replaced
34313:f428c347d32b | 34314:a667f0ca1d5f |
---|---|
102 float(self.ui.config( | 102 float(self.ui.config( |
103 'progress', 'changedelay'))) | 103 'progress', 'changedelay'))) |
104 self.order = self.ui.configlist( | 104 self.order = self.ui.configlist( |
105 'progress', 'format', | 105 'progress', 'format', |
106 default=['topic', 'bar', 'number', 'estimate']) | 106 default=['topic', 'bar', 'number', 'estimate']) |
107 self.estimateinterval = self.ui.configwith( | |
108 float, 'progress', 'estimateinterval') | |
107 | 109 |
108 def show(self, now, topic, pos, item, unit, total): | 110 def show(self, now, topic, pos, item, unit, total): |
109 if not shouldprint(self.ui): | 111 if not shouldprint(self.ui): |
110 return | 112 return |
111 termwidth = self.width() | 113 termwidth = self.width() |
236 or now - self.lastprint >= self.changedelay): | 238 or now - self.lastprint >= self.changedelay): |
237 return True | 239 return True |
238 else: | 240 else: |
239 return False | 241 return False |
240 | 242 |
243 def _calibrateestimate(self, topic, now, pos): | |
244 '''Adjust starttimes and startvals for topic so ETA works better | |
245 | |
246 If progress is non-linear (ex. get much slower in the last minute), | |
247 it's more friendly to only use a recent time span for ETA and speed | |
248 calculation. | |
249 | |
250 [======================================> ] | |
251 ^^^^^^^ | |
252 estimateinterval, only use this for estimation | |
253 ''' | |
254 interval = self.estimateinterval | |
255 if interval <= 0: | |
256 return | |
257 elapsed = now - self.starttimes[topic] | |
258 if elapsed > interval: | |
259 delta = pos - self.startvals[topic] | |
260 newdelta = delta * interval / elapsed | |
261 # If a stall happens temporarily, ETA could change dramatically | |
262 # frequently. This is to avoid such dramatical change and make ETA | |
263 # smoother. | |
264 if newdelta < 0.1: | |
265 return | |
266 self.startvals[topic] = pos - newdelta | |
267 self.starttimes[topic] = now - interval | |
268 | |
241 def progress(self, topic, pos, item='', unit='', total=None): | 269 def progress(self, topic, pos, item='', unit='', total=None): |
242 now = time.time() | 270 now = time.time() |
243 self._refreshlock.acquire() | 271 self._refreshlock.acquire() |
244 try: | 272 try: |
245 if pos is None: | 273 if pos is None: |
266 self.starttimes[topic] = now | 294 self.starttimes[topic] = now |
267 self.startvals[topic] = pos | 295 self.startvals[topic] = pos |
268 self.topics.append(topic) | 296 self.topics.append(topic) |
269 self.topicstates[topic] = pos, item, unit, total | 297 self.topicstates[topic] = pos, item, unit, total |
270 self.curtopic = topic | 298 self.curtopic = topic |
299 self._calibrateestimate(topic, now, pos) | |
271 if now - self.lastprint >= self.refresh and self.topics: | 300 if now - self.lastprint >= self.refresh and self.topics: |
272 if self._oktoprint(now): | 301 if self._oktoprint(now): |
273 self.lastprint = now | 302 self.lastprint = now |
274 self.show(now, topic, *self.topicstates[topic]) | 303 self.show(now, topic, *self.topicstates[topic]) |
275 finally: | 304 finally: |