From 1fff888e35307bcc829f901bd11ac82f0039712c Mon Sep 17 00:00:00 2001 From: "Chayim I. Kirshen" Date: Thu, 23 Feb 2023 16:55:48 +0200 Subject: [PATCH 1/3] speeding up the protocol parser --- redis/asyncio/connection.py | 22 ++++++++++------------ redis/connection.py | 24 +++++++++++------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/redis/asyncio/connection.py b/redis/asyncio/connection.py index e77fba30da..53e9099b0e 100644 --- a/redis/asyncio/connection.py +++ b/redis/asyncio/connection.py @@ -267,9 +267,6 @@ async def _read_response( response: Any byte, response = raw[:1], raw[1:] - if byte not in (b"-", b"+", b":", b"$", b"*"): - raise InvalidResponse(f"Protocol Error: {raw!r}") - # server returned an error if byte == b"-": response = response.decode("utf-8", errors="replace") @@ -291,19 +288,20 @@ async def _read_response( elif byte == b":": response = int(response) # bulk response - elif byte == b"$": - length = int(response) - if length == -1: + elif byte == b"$" and response == b'-1': return None - response = await self._read(length) + elif byte == b"$" and response != b'-1': + response = await self._read(int(response)) # multi-bulk response - elif byte == b"*": - length = int(response) - if length == -1: - return None + elif byte == b"*" and response == b'-1': + return None + elif byte == b"*" and response != b'-1': response = [ - (await self._read_response(disable_decoding)) for _ in range(length) + (await self._read_response(disable_decoding)) for _ in range(int(response)) ] + elif byte not in (b"-", b"+", b":", b"$", b"*"): + raise InvalidResponse(f"Protocol Error: {raw!r}") + if isinstance(response, bytes) and disable_decoding is False: response = self.encoder.decode(response) return response diff --git a/redis/connection.py b/redis/connection.py index d35980c167..7ca258f25e 100644 --- a/redis/connection.py +++ b/redis/connection.py @@ -358,9 +358,6 @@ def _read_response(self, disable_decoding=False): byte, response = raw[:1], raw[1:] - if byte not in (b"-", b"+", b":", b"$", b"*"): - raise InvalidResponse(f"Protocol Error: {raw!r}") - # server returned an error if byte == b"-": response = response.decode("utf-8", errors="replace") @@ -381,20 +378,21 @@ def _read_response(self, disable_decoding=False): elif byte == b":": response = int(response) # bulk response - elif byte == b"$": - length = int(response) - if length == -1: - return None - response = self._buffer.read(length) + elif byte == b"$" and response == b'-1': + return None + elif byte == b"$" and response != b'-1': + response = self._buffer.read(int(response)) # multi-bulk response - elif byte == b"*": - length = int(response) - if length == -1: - return None + elif byte == b"*" and response == b'-1': + return None + elif byte == b"*" and response != b'-1': response = [ self._read_response(disable_decoding=disable_decoding) - for i in range(length) + for i in range(int(response)) ] + elif byte not in (b"-", b"+", b":", b"$", b"*"): + raise InvalidResponse(f"Protocol Error: {raw!r}") + if isinstance(response, bytes) and disable_decoding is False: response = self.encoder.decode(response) return response From 5e716b23b0aad72b895625821b87c58ac3558394 Mon Sep 17 00:00:00 2001 From: "Chayim I. Kirshen" Date: Thu, 23 Feb 2023 17:07:29 +0200 Subject: [PATCH 2/3] linting --- redis/asyncio/connection.py | 13 +++++++------ redis/connection.py | 8 ++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/redis/asyncio/connection.py b/redis/asyncio/connection.py index 53e9099b0e..39d965bfd8 100644 --- a/redis/asyncio/connection.py +++ b/redis/asyncio/connection.py @@ -288,16 +288,17 @@ async def _read_response( elif byte == b":": response = int(response) # bulk response - elif byte == b"$" and response == b'-1': - return None - elif byte == b"$" and response != b'-1': + elif byte == b"$" and response == b"-1": + return None + elif byte == b"$" and response != b"-1": response = await self._read(int(response)) # multi-bulk response - elif byte == b"*" and response == b'-1': + elif byte == b"*" and response == b"-1": return None - elif byte == b"*" and response != b'-1': + elif byte == b"*" and response != b"-1": response = [ - (await self._read_response(disable_decoding)) for _ in range(int(response)) + (await self._read_response(disable_decoding)) + for _ in range(int(response)) # noqa ] elif byte not in (b"-", b"+", b":", b"$", b"*"): raise InvalidResponse(f"Protocol Error: {raw!r}") diff --git a/redis/connection.py b/redis/connection.py index 7ca258f25e..729ef81015 100644 --- a/redis/connection.py +++ b/redis/connection.py @@ -378,14 +378,14 @@ def _read_response(self, disable_decoding=False): elif byte == b":": response = int(response) # bulk response - elif byte == b"$" and response == b'-1': + elif byte == b"$" and response == b"-1": return None - elif byte == b"$" and response != b'-1': + elif byte == b"$" and response != b"-1": response = self._buffer.read(int(response)) # multi-bulk response - elif byte == b"*" and response == b'-1': + elif byte == b"*" and response == b"-1": return None - elif byte == b"*" and response != b'-1': + elif byte == b"*" and response != b"-1": response = [ self._read_response(disable_decoding=disable_decoding) for i in range(int(response)) From a5416f45085835ff6525631babaeaa7cf64a9e62 Mon Sep 17 00:00:00 2001 From: "Chayim I. Kirshen" Date: Sun, 26 Feb 2023 10:58:30 +0200 Subject: [PATCH 3/3] changes to ease --- redis/asyncio/connection.py | 10 +++++----- redis/connection.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/redis/asyncio/connection.py b/redis/asyncio/connection.py index 39d965bfd8..056998e9e0 100644 --- a/redis/asyncio/connection.py +++ b/redis/asyncio/connection.py @@ -286,24 +286,24 @@ async def _read_response( pass # int value elif byte == b":": - response = int(response) + return int(response) # bulk response elif byte == b"$" and response == b"-1": return None - elif byte == b"$" and response != b"-1": + elif byte == b"$": response = await self._read(int(response)) # multi-bulk response elif byte == b"*" and response == b"-1": return None - elif byte == b"*" and response != b"-1": + elif byte == b"*": response = [ (await self._read_response(disable_decoding)) for _ in range(int(response)) # noqa ] - elif byte not in (b"-", b"+", b":", b"$", b"*"): + else: raise InvalidResponse(f"Protocol Error: {raw!r}") - if isinstance(response, bytes) and disable_decoding is False: + if disable_decoding is False: response = self.encoder.decode(response) return response diff --git a/redis/connection.py b/redis/connection.py index 729ef81015..c4a9685f6a 100644 --- a/redis/connection.py +++ b/redis/connection.py @@ -376,24 +376,24 @@ def _read_response(self, disable_decoding=False): pass # int value elif byte == b":": - response = int(response) + return int(response) # bulk response elif byte == b"$" and response == b"-1": return None - elif byte == b"$" and response != b"-1": + elif byte == b"$": response = self._buffer.read(int(response)) # multi-bulk response elif byte == b"*" and response == b"-1": return None - elif byte == b"*" and response != b"-1": + elif byte == b"*": response = [ self._read_response(disable_decoding=disable_decoding) for i in range(int(response)) ] - elif byte not in (b"-", b"+", b":", b"$", b"*"): + else: raise InvalidResponse(f"Protocol Error: {raw!r}") - if isinstance(response, bytes) and disable_decoding is False: + if disable_decoding is False: response = self.encoder.decode(response) return response