Mercurial > public > mercurial-scm > hg
comparison mercurial/util.py @ 25672:050dc6eabc92
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.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Fri, 26 Jun 2015 11:29:50 -0700 |
parents | d5ac3bebaf2a |
children | ce26928cbe41 |
comparison
equal
deleted
inserted
replaced
25671:d5ac3bebaf2a | 25672:050dc6eabc92 |
---|---|
252 | 252 |
253 def __init__(self, input): | 253 def __init__(self, input): |
254 self._input = input | 254 self._input = input |
255 self._buffer = [] | 255 self._buffer = [] |
256 self._eof = False | 256 self._eof = False |
257 self._lenbuf = 0 | |
257 | 258 |
258 @property | 259 @property |
259 def hasbuffer(self): | 260 def hasbuffer(self): |
260 """True is any data is currently buffered | 261 """True is any data is currently buffered |
261 | 262 |
281 def readline(self, *args, **kwargs): | 282 def readline(self, *args, **kwargs): |
282 if 1 < len(self._buffer): | 283 if 1 < len(self._buffer): |
283 # this should not happen because both read and readline end with a | 284 # this should not happen because both read and readline end with a |
284 # _frombuffer call that collapse it. | 285 # _frombuffer call that collapse it. |
285 self._buffer = [''.join(self._buffer)] | 286 self._buffer = [''.join(self._buffer)] |
287 self._lenbuf = len(self._buffer[0]) | |
286 lfi = -1 | 288 lfi = -1 |
287 if self._buffer: | 289 if self._buffer: |
288 lfi = self._buffer[-1].find('\n') | 290 lfi = self._buffer[-1].find('\n') |
289 while (not self._eof) and lfi < 0: | 291 while (not self._eof) and lfi < 0: |
290 self._fillbuffer() | 292 self._fillbuffer() |
296 elif 1 < len(self._buffer): | 298 elif 1 < len(self._buffer): |
297 # we need to take previous chunks into account | 299 # we need to take previous chunks into account |
298 size += self._lenbuf - len(self._buffer[-1]) | 300 size += self._lenbuf - len(self._buffer[-1]) |
299 return self._frombuffer(size) | 301 return self._frombuffer(size) |
300 | 302 |
301 @property | |
302 def _lenbuf(self): | |
303 """return the current lengh of buffered data""" | |
304 return sum(len(d) for d in self._buffer) | |
305 | |
306 def _frombuffer(self, size): | 303 def _frombuffer(self, size): |
307 """return at most 'size' data from the buffer | 304 """return at most 'size' data from the buffer |
308 | 305 |
309 The data are removed from the buffer.""" | 306 The data are removed from the buffer.""" |
310 if size == 0 or not self._buffer: | 307 if size == 0 or not self._buffer: |
315 | 312 |
316 data = buf[:size] | 313 data = buf[:size] |
317 buf = buf[len(data):] | 314 buf = buf[len(data):] |
318 if buf: | 315 if buf: |
319 self._buffer = [buf] | 316 self._buffer = [buf] |
317 self._lenbuf = len(buf) | |
320 else: | 318 else: |
321 self._buffer = [] | 319 self._buffer = [] |
320 self._lenbuf = 0 | |
322 return data | 321 return data |
323 | 322 |
324 def _fillbuffer(self): | 323 def _fillbuffer(self): |
325 """read data to the buffer""" | 324 """read data to the buffer""" |
326 data = os.read(self._input.fileno(), _chunksize) | 325 data = os.read(self._input.fileno(), _chunksize) |
327 if not data: | 326 if not data: |
328 self._eof = True | 327 self._eof = True |
329 else: | 328 else: |
329 self._lenbuf += len(data) | |
330 self._buffer.append(data) | 330 self._buffer.append(data) |
331 | 331 |
332 def popen2(cmd, env=None, newlines=False): | 332 def popen2(cmd, env=None, newlines=False): |
333 # Setting bufsize to -1 lets the system decide the buffer size. | 333 # Setting bufsize to -1 lets the system decide the buffer size. |
334 # The default for bufsize is 0, meaning unbuffered. This leads to | 334 # The default for bufsize is 0, meaning unbuffered. This leads to |