http2: make read use pushchunk/popchunk, eschew itertools
authorBrendan Cully <brendan@kublai.com>
Fri, 01 Feb 2013 14:41:35 -0800
changeset 19037 1fde25ad9396
parent 19036 19d1cc30e7a3
child 19038 36733ab7fa05
http2: make read use pushchunk/popchunk, eschew itertools The itertools approach was showing up high in the profile output.
mercurial/httpclient/_readers.py
--- 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