http2: make read use pushchunk/popchunk, eschew itertools
The itertools approach was showing up high in the profile output.
--- a/mercurial/httpclient/_readers.py Fri Feb 01 14:41:33 2013 -0800
+++ b/mercurial/httpclient/_readers.py Fri Feb 01 14:41:35 2013 -0800
@@ -79,22 +79,21 @@
def read(self, amt):
if self.available_data < amt and not self._finished:
raise ReadNotReady()
- need = [amt]
- def pred(s):
- needed = need[0] > 0
- need[0] -= len(s)
- return needed
- blocks = list(itertools.takewhile(pred, self._done_chunks))
- self._done_chunks = self._done_chunks[len(blocks):]
- over_read = sum(map(len, blocks)) - amt
- if over_read > 0 and blocks:
- logger.debug('need to reinsert %d data into done chunks', over_read)
- last = blocks[-1]
- blocks[-1], reinsert = last[:-over_read], last[-over_read:]
- self._done_chunks.insert(0, reinsert)
+ blocks = []
+ need = amt
+ while self._done_chunks:
+ b = self.popchunk()
+ if len(b) > need:
+ nb = b[:need]
+ self.pushchunk(b[need:])
+ b = nb
+ blocks.append(b)
+ need -= len(b)
+ if need == 0:
+ break
result = ''.join(blocks)
assert len(result) == amt or (self._finished and len(result) < amt)
- self.available_data -= amt
+
return result
def _load(self, data): # pragma: no cover