diff options
author | Yury Selivanov <yury@magic.io> | 2016-10-05 22:01:12 (GMT) |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2016-10-05 22:01:12 (GMT) |
commit | 3e56ff0d08a65ea1e0fe361ae22d855acc9d65bb (patch) | |
tree | 468e4957435e220f4134db1185cbe2dc15b91a3d /Lib/asyncio/streams.py | |
parent | 5b8d4f97f8bbb357d7c8b79007fdff22e2c8d1ae (diff) | |
download | cpython-3e56ff0d08a65ea1e0fe361ae22d855acc9d65bb.zip cpython-3e56ff0d08a65ea1e0fe361ae22d855acc9d65bb.tar.gz cpython-3e56ff0d08a65ea1e0fe361ae22d855acc9d65bb.tar.bz2 |
Issue #28370: Speedup asyncio.StreamReader.readexactly
Patch by Коренберг Марк.
Diffstat (limited to 'Lib/asyncio/streams.py')
-rw-r--r-- | Lib/asyncio/streams.py | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index b4adc7d..a82cc79 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -448,6 +448,7 @@ class StreamReader: assert not self._eof, '_wait_for_data after EOF' # Waiting for data while paused will make deadlock, so prevent it. + # This is essential for readexactly(n) for case when n > self._limit. if self._paused: self._paused = False self._transport.resume_reading() @@ -658,25 +659,22 @@ class StreamReader: if n == 0: return b'' - # There used to be "optimized" code here. It created its own - # Future and waited until self._buffer had at least the n - # bytes, then called read(n). Unfortunately, this could pause - # the transport if the argument was larger than the pause - # limit (which is twice self._limit). So now we just read() - # into a local buffer. - - blocks = [] - while n > 0: - block = yield from self.read(n) - if not block: - partial = b''.join(blocks) - raise IncompleteReadError(partial, len(partial) + n) - blocks.append(block) - n -= len(block) - - assert n == 0 - - return b''.join(blocks) + while len(self._buffer) < n: + if self._eof: + incomplete = bytes(self._buffer) + self._buffer.clear() + raise IncompleteReadError(incomplete, n) + + yield from self._wait_for_data('readexactly') + + if len(self._buffer) == n: + data = bytes(self._buffer) + self._buffer.clear() + else: + data = bytes(self._buffer[:n]) + del self._buffer[:n] + self._maybe_resume_transport() + return data if compat.PY35: @coroutine |