# HG changeset patch # User Gregory Szorc # Date 1444258965 25200 # Node ID dc5b594f41e9be5820ce3f197d3817379b2d3af5 # Parent 5d06f6b73a5727c9a993f493eb0d694229bd13ae keepalive: rewrite readline() The old method was performing string concatenation, which is slower than collecting raw chunks in a list and joining at the end. diff -r 5d06f6b73a57 -r dc5b594f41e9 mercurial/keepalive.py --- a/mercurial/keepalive.py Wed Oct 07 15:53:58 2015 -0700 +++ b/mercurial/keepalive.py Wed Oct 07 16:02:45 2015 -0700 @@ -452,21 +452,39 @@ return ''.join(parts) def readline(self): + # Fast path for a line is already available in read buffer. i = self._rbuf.find('\n') - while i < 0: - new = self._raw_read(self._rbufsize) + if i >= 0: + i += 1 + line = self._rbuf[:i] + self._rbuf = self._rbuf[i:] + return line + + # No newline in local buffer. Read until we find one. + chunks = [self._rbuf] + i = -1 + readsize = self._rbufsize + while True: + new = self._raw_read(readsize) if not new: break + + chunks.append(new) i = new.find('\n') if i >= 0: - i = i + len(self._rbuf) - self._rbuf = self._rbuf + new - if i < 0: - i = len(self._rbuf) - else: - i = i + 1 - data, self._rbuf = self._rbuf[:i], self._rbuf[i:] - return data + break + + # We either have exhausted the stream or have a newline in chunks[-1]. + + # EOF + if i == -1: + self._rbuf = '' + return ''.join(chunks) + + i += 1 + self._rbuf = chunks[-1][i:] + chunks[-1] = chunks[-1][:i] + return ''.join(chunks) def readlines(self, sizehint=0): total = 0