[PATCH 2 of 2 V2] bufferedinputpipe: remove N^2 computation of buffer length (issue4735)

Pierre-Yves David pierre-yves.david at ens-lyon.org
Fri Jun 26 20:59:40 CDT 2015


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1435343390 25200
#      Fri Jun 26 11:29:50 2015 -0700
# Node ID 97ef869907f9097a4de6dfa168301a62ad6f818f
# Parent  995f1afb89fac10d4759d6c3524693ecb926b9f4
bufferedinputpipe: remove N^2 computation of buffer length (issue4735)

The assumption that dynamically computing the length of the buffer was N^2, but
negligible because fast was False. So we drop the dynamic computation and
manually keep track of the buffer length.

He: Enter commit message.  Lines beginning with 'HG:' are removed.

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -252,10 +252,11 @@ class bufferedinputpipe(object):
 
     def __init__(self, input):
         self._input = input
         self._buffer = []
         self._eof = False
+        self._lenbuf = 0
 
     @property
     def hasbuffer(self):
         """True is any data is currently buffered
 
@@ -281,10 +282,11 @@ class bufferedinputpipe(object):
     def readline(self, *args, **kwargs):
         if 1 < len(self._buffer):
             # this should not happen because both read and readline end with a
             # _frombuffer call that collapse it.
             self._buffer = [''.join(self._buffer)]
+            self._lenbuf = len(self._buffer[0])
         lfi = -1
         if self._buffer:
             lfi = self._buffer[-1].find('\n')
         while (not self._eof) and lfi < 0:
             self._fillbuffer()
@@ -296,15 +298,10 @@ class bufferedinputpipe(object):
         elif 1 < len(self._buffer):
             # we need to take previous chunks into account
             size += self._lenbuf - len(self._buffer[-1])
         return self._frombuffer(size)
 
-    @property
-    def _lenbuf(self):
-        """return the current lengh of buffered data"""
-        return sum(len(d) for d in self._buffer)
-
     def _frombuffer(self, size):
         """return at most 'size' data from the buffer
 
         The data are removed from the buffer."""
         if size == 0 or not self._buffer:
@@ -315,20 +312,23 @@ class bufferedinputpipe(object):
 
         data = buf[:size]
         buf = buf[len(data):]
         if buf:
             self._buffer = [buf]
+            self._lenbuf = len(buf)
         else:
             self._buffer = []
+            self._lenbuf = 0
         return data
 
     def _fillbuffer(self):
         """read data to the buffer"""
         data = os.read(self._input.fileno(), _chunksize)
         if not data:
             self._eof = True
         else:
+            self._lenbuf += len(data)
             self._buffer.append(data)
 
 def popen2(cmd, env=None, newlines=False):
     # Setting bufsize to -1 lets the system decide the buffer size.
     # The default for bufsize is 0, meaning unbuffered. This leads to


More information about the Mercurial-devel mailing list