changeset 30688:dc5b594f41e9

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.
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 07 Oct 2015 16:02:45 -0700
parents 5d06f6b73a57
children 9fa7255d4abd
files mercurial/keepalive.py
diffstat 1 files changed, 28 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- 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