diff -r 5a9e4dc8e4fd -r fdecd24ca4dc mercurial/ui.py --- a/mercurial/ui.py Wed Feb 15 13:07:26 2017 -0800 +++ b/mercurial/ui.py Wed Feb 15 13:50:06 2017 -0800 @@ -199,6 +199,7 @@ @contextlib.contextmanager def timeblockedsection(self, key): + # this is open-coded below - search for timeblockedsection to find them starttime = util.timer() try: yield @@ -776,31 +777,44 @@ self._buffers[-1].extend(a for a in args) else: self._progclear() - for a in args: - self.fout.write(a) + # opencode timeblockedsection because this is a critical path + starttime = util.timer() + try: + for a in args: + self.fout.write(a) + finally: + self._blockedtimes['stdio_blocked'] += \ + (util.timer() - starttime) * 1000 def write_err(self, *args, **opts): self._progclear() try: if self._bufferstates and self._bufferstates[-1][0]: return self.write(*args, **opts) - if not getattr(self.fout, 'closed', False): - self.fout.flush() - for a in args: - self.ferr.write(a) - # stderr may be buffered under win32 when redirected to files, - # including stdout. - if not getattr(self.ferr, 'closed', False): - self.ferr.flush() + with self.timeblockedsection('stdio'): + if not getattr(self.fout, 'closed', False): + self.fout.flush() + for a in args: + self.ferr.write(a) + # stderr may be buffered under win32 when redirected to files, + # including stdout. + if not getattr(self.ferr, 'closed', False): + self.ferr.flush() except IOError as inst: if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF): raise def flush(self): - try: self.fout.flush() - except (IOError, ValueError): pass - try: self.ferr.flush() - except (IOError, ValueError): pass + # opencode timeblockedsection because this is a critical path + starttime = util.timer() + try: + try: self.fout.flush() + except (IOError, ValueError): pass + try: self.ferr.flush() + except (IOError, ValueError): pass + finally: + self._blockedtimes['stdio_blocked'] += \ + (util.timer() - starttime) * 1000 def _isatty(self, fh): if self.configbool('ui', 'nontty', False): @@ -962,7 +976,8 @@ sys.stdout = self.fout # prompt ' ' must exist; otherwise readline may delete entire line # - http://bugs.python.org/issue12833 - line = raw_input(' ') + with self.timeblockedsection('stdio'): + line = raw_input(' ') sys.stdin = oldin sys.stdout = oldout @@ -1042,13 +1057,14 @@ self.write_err(self.label(prompt or _('password: '), 'ui.prompt')) # disable getpass() only if explicitly specified. it's still valid # to interact with tty even if fin is not a tty. - if self.configbool('ui', 'nontty'): - l = self.fin.readline() - if not l: - raise EOFError - return l.rstrip('\n') - else: - return getpass.getpass('') + with self.timeblockedsection('stdio'): + if self.configbool('ui', 'nontty'): + l = self.fin.readline() + if not l: + raise EOFError + return l.rstrip('\n') + else: + return getpass.getpass('') except EOFError: raise error.ResponseExpected() def status(self, *msg, **opts):