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

login
register
mail settings
Submitter Pierre-Yves David
Date June 27, 2015, 1:59 a.m.
Message ID <97ef869907f9097a4de6.1435370380@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/9797/
State Accepted
Commit 050dc6eabc92b4d280d16da4c1661ea76c68d7fa
Headers show

Comments

Pierre-Yves David - June 27, 2015, 1:59 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@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.
Durham Goode - June 27, 2015, 6:57 p.m.
On 6/26/15, 6:59 PM, "Pierre-Yves David" <pierre-yves.david@ens-lyon.org>
wrote:

># HG changeset patch
># User Pierre-Yves David <pierre-yves.david@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.

Pushed to clowncopter (after removing the accidental 'He: ...' message
line). Thanks

Patch

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