Unverified Kaydet (Commit) d6bf6f2d authored tarafından Inada Naoki's avatar Inada Naoki Kaydeden (comit) GitHub

bpo-36050: optimize HTTPResponse.read() (GH-12698)

* No need to chunking for now.
* No need to partial read caused by EINTR for now.
üst a0da131a
...@@ -105,9 +105,6 @@ globals().update(http.HTTPStatus.__members__) ...@@ -105,9 +105,6 @@ globals().update(http.HTTPStatus.__members__)
# Mapping status codes to official W3C names # Mapping status codes to official W3C names
responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()} responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}
# maximal amount of data to read at one time in _safe_read
MAXAMOUNT = 1048576
# maximal line length when calling readline(). # maximal line length when calling readline().
_MAXLINE = 65536 _MAXLINE = 65536
_MAXHEADERS = 100 _MAXHEADERS = 100
...@@ -592,43 +589,24 @@ class HTTPResponse(io.BufferedIOBase): ...@@ -592,43 +589,24 @@ class HTTPResponse(io.BufferedIOBase):
raise IncompleteRead(bytes(b[0:total_bytes])) raise IncompleteRead(bytes(b[0:total_bytes]))
def _safe_read(self, amt): def _safe_read(self, amt):
"""Read the number of bytes requested, compensating for partial reads. """Read the number of bytes requested.
Normally, we have a blocking socket, but a read() can be interrupted
by a signal (resulting in a partial read).
Note that we cannot distinguish between EOF and an interrupt when zero
bytes have been read. IncompleteRead() will be raised in this
situation.
This function should be used when <amt> bytes "should" be present for This function should be used when <amt> bytes "should" be present for
reading. If the bytes are truly not available (due to EOF), then the reading. If the bytes are truly not available (due to EOF), then the
IncompleteRead exception can be used to detect the problem. IncompleteRead exception can be used to detect the problem.
""" """
s = [] data = self.fp.read(amt)
while amt > 0: if len(data) < amt:
chunk = self.fp.read(min(amt, MAXAMOUNT)) raise IncompleteRead(data, amt-len(data))
if not chunk: return data
raise IncompleteRead(b''.join(s), amt)
s.append(chunk)
amt -= len(chunk)
return b"".join(s)
def _safe_readinto(self, b): def _safe_readinto(self, b):
"""Same as _safe_read, but for reading into a buffer.""" """Same as _safe_read, but for reading into a buffer."""
total_bytes = 0 amt = len(b)
mvb = memoryview(b) n = self.fp.readinto(b)
while total_bytes < len(b): if n < amt:
if MAXAMOUNT < len(mvb): raise IncompleteRead(bytes(b[:n]), amt-n)
temp_mvb = mvb[0:MAXAMOUNT] return n
n = self.fp.readinto(temp_mvb)
else:
n = self.fp.readinto(mvb)
if not n:
raise IncompleteRead(bytes(mvb[0:total_bytes]), len(b))
mvb = mvb[n:]
total_bytes += n
return total_bytes
def read1(self, n=-1): def read1(self, n=-1):
"""Read with at most one underlying system call. If at least one """Read with at most one underlying system call. If at least one
......
Optimized ``http.client.HTTPResponse.read()`` for large response. Patch by
Inada Naoki.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment