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: