diff options
author | Nick Pope <nick@nickpope.me.uk> | 2022-07-22 21:08:10 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-01-05 19:26:56 +0100 |
commit | b47f2f5b907732d80b164f1f361ae39da94a3fa6 (patch) | |
tree | 437f0c92ea2b17816d1ad7f200ed077d44c8bce8 /tests/builtin_server | |
parent | 57f5669d23fe17d940887e1e3ce694c7366a6330 (diff) | |
download | django-b47f2f5b907732d80b164f1f361ae39da94a3fa6.tar.gz |
Fixed #33865 -- Optimized LimitedStream wrapper.
The current implementation of LimitedStream is slow because .read()
performs an extra copy into a buffer and .readline() performs two
extra copies. The stream being wrapped is already typically a BytesIO
object so this is unnecessary.
This implementation has largely been untouched for 12 years and,
inspired by a simpler implementation in werkzeug, it was possible to
achieve the following performance improvement:
LimitedStream.read() (single line):
Mean +- std dev: [bench_limitedstream-main] 286 ns +- 6 ns
-> [bench_limitedstream-patch] 227 ns +- 6 ns: 1.26x faster
LimitedStream.readline() (single line):
Mean +- std dev: [bench_limitedstream-main] 507 ns +- 11 ns
-> [bench_limitedstream-patch] 232 ns +- 8 ns: 2.18x faster
LimitedStream.read(8192) (single line):
Mean +- std dev: [bench_limitedstream-main] 360 ns +- 8 ns
-> [bench_limitedstream-patch] 297 ns +- 6 ns: 1.21x faster
LimitedStream.readline(8192) (single line):
Mean +- std dev: [bench_limitedstream-main] 602 ns +- 10 ns
-> [bench_limitedstream-patch] 305 ns +- 10 ns: 1.98x faster
LimitedStream.read() (multiple lines):
Mean +- std dev: [bench_limitedstream-main] 290 ns +- 5 ns
-> [bench_limitedstream-patch] 236 ns +- 6 ns: 1.23x faster
LimitedStream.readline() (multiple lines):
Mean +- std dev: [bench_limitedstream-main] 517 ns +- 19 ns
-> [bench_limitedstream-patch] 239 ns +- 7 ns: 2.16x faster
LimitedStream.read(8192) (multiple lines):
Mean +- std dev: [bench_limitedstream-main] 363 ns +- 8 ns
-> [bench_limitedstream-patch] 311 ns +- 11 ns: 1.17x faster
LimitedStream.readline(8192) (multiple lines):
Mean +- std dev: [bench_limitedstream-main] 601 ns +- 12 ns
-> [bench_limitedstream-patch] 308 ns +- 7 ns: 1.95x faster
Geometric mean: 1.59x faster
Diffstat (limited to 'tests/builtin_server')
-rw-r--r-- | tests/builtin_server/tests.py | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/tests/builtin_server/tests.py b/tests/builtin_server/tests.py index 2777db1e13..f654fdd92c 100644 --- a/tests/builtin_server/tests.py +++ b/tests/builtin_server/tests.py @@ -81,7 +81,7 @@ class WSGIFileWrapperTests(TestCase): def test_file_wrapper_uses_sendfile(self): env = {"SERVER_PROTOCOL": "HTTP/1.0"} - handler = FileWrapperHandler(None, BytesIO(), BytesIO(), env) + handler = FileWrapperHandler(BytesIO(), BytesIO(), BytesIO(), env) handler.run(wsgi_app_file_wrapper) self.assertTrue(handler._used_sendfile) self.assertEqual(handler.stdout.getvalue(), b"") @@ -89,7 +89,7 @@ class WSGIFileWrapperTests(TestCase): def test_file_wrapper_no_sendfile(self): env = {"SERVER_PROTOCOL": "HTTP/1.0"} - handler = FileWrapperHandler(None, BytesIO(), BytesIO(), env) + handler = FileWrapperHandler(BytesIO(), BytesIO(), BytesIO(), env) handler.run(wsgi_app) self.assertFalse(handler._used_sendfile) self.assertEqual(handler.stdout.getvalue().splitlines()[-1], b"Hello World!") @@ -102,7 +102,7 @@ class WSGIFileWrapperTests(TestCase): response when file_wrapper is used. """ env = RequestFactory().get("/fileresponse/").environ - handler = FileWrapperHandler(None, BytesIO(), BytesIO(), env) + handler = FileWrapperHandler(BytesIO(), BytesIO(), BytesIO(), env) handler.run(get_internal_wsgi_application()) # Sendfile is used only when file_wrapper has been used. self.assertTrue(handler._used_sendfile) @@ -119,7 +119,7 @@ class WSGIFileWrapperTests(TestCase): @override_settings(ROOT_URLCONF="builtin_server.urls") def test_file_response_call_request_finished(self): env = RequestFactory().get("/fileresponse/").environ - handler = FileWrapperHandler(None, BytesIO(), BytesIO(), env) + handler = FileWrapperHandler(BytesIO(), BytesIO(), BytesIO(), env) with mock.MagicMock() as signal_handler: request_finished.connect(signal_handler) handler.run(get_internal_wsgi_application()) |