From: Ben Darnell Date: Sun, 2 Aug 2015 19:32:24 +0000 (-0400) Subject: Reduce default compression to level 6; raise min compressible length. X-Git-Tag: v4.3.0b1~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa7ccba45cad99c1b20f4bb95dab77afcd2a882b;p=thirdparty%2Ftornado.git Reduce default compression to level 6; raise min compressible length. Partially addresses #1095. --- diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index b301c7e6e..dc4c865bb 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -205,6 +205,7 @@ class SimpleHTTPClientTestMixin(object): self.assertEqual(response.headers["Content-Encoding"], "gzip") self.assertNotEqual(response.body, b"asdfqwer") # Our test data gets bigger when gzipped. Oops. :) + # Chunked encoding bypasses the MIN_LENGTH check. self.assertEqual(len(response.body), 34) f = gzip.GzipFile(mode="r", fileobj=response.buffer) self.assertEqual(f.read(), b"asdfqwer") diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index 85c7552c9..5938b7b68 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -11,7 +11,7 @@ from tornado.template import DictLoader from tornado.testing import AsyncHTTPTestCase, ExpectLog, gen_test from tornado.test.util import unittest from tornado.util import u, ObjectDict, unicode_type, timedelta_to_seconds -from tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature_v1, create_signed_value, decode_signed_value, ErrorHandler, UIModule, MissingArgumentError, stream_request_body, Finish, removeslash, addslash, RedirectHandler as WebRedirectHandler, get_signature_key_version +from tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature_v1, create_signed_value, decode_signed_value, ErrorHandler, UIModule, MissingArgumentError, stream_request_body, Finish, removeslash, addslash, RedirectHandler as WebRedirectHandler, get_signature_key_version, GZipContentEncoding import binascii import contextlib @@ -1483,7 +1483,8 @@ class GzipTestCase(SimpleHandlerTestCase): def get(self): if self.get_argument('vary', None): self.set_header('Vary', self.get_argument('vary')) - self.write('hello world') + # Must write at least MIN_LENGTH bytes to activate compression. + self.write('hello world' + ('!' * GZipContentEncoding.MIN_LENGTH)) def get_app_kwargs(self): return dict( diff --git a/tornado/web.py b/tornado/web.py index b2fa6086e..b6197ce7e 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -2658,7 +2658,16 @@ class GZipContentEncoding(OutputTransform): CONTENT_TYPES = set(["application/javascript", "application/x-javascript", "application/xml", "application/atom+xml", "application/json", "application/xhtml+xml"]) - MIN_LENGTH = 5 + # Python's GzipFile defaults to level 9, while most other gzip + # tools (including gzip itself) default to 6, which is probably a + # better CPU/size tradeoff. + GZIP_LEVEL = 6 + # Responses that are too short are unlikely to benefit from gzipping + # after considering the "Content-Encoding: gzip" header and the header + # inside the gzip encoding. + # Note that responses written in multiple chunks will be compressed + # regardless of size. + MIN_LENGTH = 1024 def __init__(self, request): self._gzipping = "gzip" in request.headers.get("Accept-Encoding", "") @@ -2679,7 +2688,8 @@ class GZipContentEncoding(OutputTransform): if self._gzipping: headers["Content-Encoding"] = "gzip" self._gzip_value = BytesIO() - self._gzip_file = gzip.GzipFile(mode="w", fileobj=self._gzip_value) + self._gzip_file = gzip.GzipFile(mode="w", fileobj=self._gzip_value, + compresslevel=self.GZIP_LEVEL) chunk = self.transform_chunk(chunk, finishing) if "Content-Length" in headers: # The original content length is no longer correct. diff --git a/tornado/websocket.py b/tornado/websocket.py index 2f57b9909..d688295ff 100644 --- a/tornado/websocket.py +++ b/tornado/websocket.py @@ -444,7 +444,8 @@ class _PerMessageDeflateCompressor(object): self._compressor = None def _create_compressor(self): - return zlib.compressobj(-1, zlib.DEFLATED, -self._max_wbits) + return zlib.compressobj(tornado.web.GZipContentEncoding.GZIP_LEVEL, + zlib.DEFLATED, -self._max_wbits) def compress(self, data): compressor = self._compressor or self._create_compressor()