From 9e308e317f4327c9dd0681c3776f2e9491b31716 Mon Sep 17 00:00:00 2001 From: Djoume Salvetti Date: Wed, 9 May 2012 10:54:59 -0400 Subject: [PATCH] Improves performance of http.body.Body.readline() --- gunicorn/http/body.py | 22 ++++++------- tests/004-test-http-body.py | 61 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 tests/004-test-http-body.py diff --git a/gunicorn/http/body.py b/gunicorn/http/body.py index feb77c36..b331f292 100644 --- a/gunicorn/http/body.py +++ b/gunicorn/http/body.py @@ -228,24 +228,20 @@ class Body(object): return "" line = self.buf.getvalue() + self.buf.truncate(0) + if len(line) < size: + line += self.reader.read(size - len(line)) + extra_buf_data = line[size:] + line = line[:size] + idx = line.find("\n") if idx >= 0: ret = line[:idx+1] - self.buf.truncate(0) self.buf.write(line[idx+1:]) + self.buf.write(extra_buf_data) return ret - - self.buf.truncate(0) - ch = "" - buf = [line] - lsize = len(line) - while lsize < size and ch != "\n": - ch = self.reader.read(1) - if not len(ch): - break - lsize += 1 - buf.append(ch) - return "".join(buf) + self.buf.write(extra_buf_data) + return line def readlines(self, size=None): ret = [] diff --git a/tests/004-test-http-body.py b/tests/004-test-http-body.py new file mode 100644 index 00000000..22357478 --- /dev/null +++ b/tests/004-test-http-body.py @@ -0,0 +1,61 @@ +from StringIO import StringIO + +import t +from gunicorn.http.body import Body + + +def assert_readline(payload, size, expected): + body = Body(StringIO(payload)) + t.eq(body.readline(size), expected) + + +def test_readline_empty_body(): + assert_readline("", None, "") + assert_readline("", 1, "") + + +def test_readline_zero_size(): + assert_readline("abc", 0, "") + assert_readline("\n", 0, "") + + +def test_readline_new_line_before_size(): + body = Body(StringIO("abc\ndef")) + t.eq(body.readline(4), "abc\n") + t.eq(body.readline(), "def") + + +def test_readline_new_line_after_size(): + body = Body(StringIO("abc\ndef")) + t.eq(body.readline(2), "ab") + t.eq(body.readline(), "c\n") + + +def test_readline_no_new_line(): + body = Body(StringIO("abcdef")) + t.eq(body.readline(), "abcdef") + body = Body(StringIO("abcdef")) + t.eq(body.readline(2), "ab") + t.eq(body.readline(2), "cd") + t.eq(body.readline(2), "ef") + + +def test_readline_buffer_loaded(): + reader = StringIO("abc\ndef") + body = Body(reader) + body.read(1) # load internal buffer + reader.write("g\nhi") + reader.seek(7) + t.eq(body.readline(), "bc\n") + t.eq(body.readline(), "defg\n") + t.eq(body.readline(), "hi") + + +def test_readline_buffer_loaded_with_size(): + body = Body(StringIO("abc\ndef")) + body.read(1) # load internal buffer + t.eq(body.readline(2), "bc") + t.eq(body.readline(2), "\n") + t.eq(body.readline(2), "de") + t.eq(body.readline(2), "f") +