Commit 45a16fa0 authored by Jason Madden's avatar Jason Madden

Use a buffer to generate HTTP chunks.

The intent is to reduce network overhead for small chunk sizes withoud adding much overhead for larger sizes.

Fixes #1233.
parent c1b473f0
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
condition that is known to lead to RecursionError. This may produce condition that is known to lead to RecursionError. This may produce
false negatives, but should reduce or eliminate false positives. false negatives, but should reduce or eliminate false positives.
- Based on measurements and discussion in :issue:`1233`, adjust the
way :mod:`gevent.pywsgi` generates HTTP chunks. This is intended to
reduce network overhead, especially for smaller chunk sizes.
1.3.3 (2018-06-08) 1.3.3 (2018-06-08)
================== ==================
......
...@@ -708,7 +708,9 @@ class WSGIHandler(object): ...@@ -708,7 +708,9 @@ class WSGIHandler(object):
raise raise
self.response_length += len(data) self.response_length += len(data)
def _write(self, data): def _write(self, data,
_PY34_EXACTLY=(sys.version_info[:2] == (3, 4)),
_bytearray=bytearray):
if not data: if not data:
# The application/middleware are allowed to yield # The application/middleware are allowed to yield
# empty bytestrings. # empty bytestrings.
...@@ -716,14 +718,25 @@ class WSGIHandler(object): ...@@ -716,14 +718,25 @@ class WSGIHandler(object):
if self.response_use_chunked: if self.response_use_chunked:
## Write the chunked encoding ## Write the chunked encoding
header = ("%x\r\n" % len(data)).encode('ascii') # header
# socket.sendall will slice these small strings, as [0:], if _PY34_EXACTLY:
# but that's special cased to return the original string. # This is the only version we support that doesn't
# They're small enough we probably expect them to go down to the network # allow % to be used with bytes. Passing a bytestring
# buffers in one go anyway. # directly in to bytearray() is faster than passing a
self._sendall(header) # (unicode) str with encoding, which naturally is faster still
self._sendall(data) # than encoding first. Interestingly, byte formatting on Python 3
self._sendall(b'\r\n') # trailer # is faster than str formatting.
header_str = '%x\r\n' % len(data)
towrite = _bytearray(header_str, 'ascii')
else:
header_str = b'%x\r\n' % len(data)
towrite = _bytearray(header_str)
# data
towrite.extend(data)
# trailer
towrite.extend(b'\r\n')
self._sendall(towrite)
else: else:
self._sendall(data) self._sendall(data)
......
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