diff options
author | James E. Blair <jeblair@redhat.com> | 2016-07-17 08:05:57 -0700 |
---|---|---|
committer | James E. Blair <jeblair@redhat.com> | 2016-07-17 08:05:57 -0700 |
commit | 2defbeaa1beb9ff9e0e3e31529f1f761ac4fcae5 (patch) | |
tree | 1beac6df51d10f8f6a2da9b2d99e3d6d1d124d83 | |
parent | 550873b76abded12cd27c054b0dab0511ffd5e36 (diff) | |
download | gear-2defbeaa1beb9ff9e0e3e31529f1f761ac4fcae5.tar.gz |
Parse admin requests 2880 times faster
Both returning the incomplete data from the isComplete method, and
scanning the entire incomplete string for the terminator each time
are O(n^2).
Also, returning the string is *very* slow, accounting for 99.6% of
the speedup; scanning the string each time accounts for 0.6%.
Both changes together find the terminus of a 481MiB response in
about 1.6 seconds compared to 76 minutes prior to this change.
Change-Id: I3614e8f3ff8ad7c3d9ca6da1b520b89cd9d5d603
-rw-r--r-- | gear/__init__.py | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/gear/__init__.py b/gear/__init__.py index d4d370f..86fb675 100644 --- a/gear/__init__.py +++ b/gear/__init__.py @@ -314,7 +314,8 @@ class Connection(object): admin_request = self._getAdminRequest() if admin: complete, remainder = admin_request.isComplete(raw_bytes) - raw_bytes = remainder + if remainder is not None: + raw_bytes = remainder if complete: return admin_request else: @@ -431,6 +432,7 @@ class AdminRequest(object): command = None arguments = [] response = None + _complete_position = 0 def __init__(self, *arguments): self.wait_event = threading.Event() @@ -451,8 +453,10 @@ class AdminRequest(object): def isComplete(self, data): x = -1 - end_index_newline = data.find(b'\n.\n') - end_index_return = data.find(b'\r\n.\r\n') + start = self._complete_position + start = max(self._complete_position - 4, 0) + end_index_newline = data.find(b'\n.\n', start) + end_index_return = data.find(b'\r\n.\r\n', start) if end_index_newline != -1: x = end_index_newline + 3 elif end_index_return != -1: @@ -461,11 +465,12 @@ class AdminRequest(object): x = 2 elif data.startswith(b'.\r\n'): x = 3 + self._complete_position = len(data) if x != -1: self.response = data[:x] return (True, data[x:]) else: - return (False, data) + return (False, None) def setComplete(self): self.wait_event.set() @@ -530,7 +535,7 @@ class CancelJobAdminRequest(AdminRequest): self.response = data[:x] return (True, data[x:]) else: - return (False, data) + return (False, None) class VersionAdminRequest(AdminRequest): @@ -551,7 +556,7 @@ class VersionAdminRequest(AdminRequest): self.response = data[:x] return (True, data[x:]) else: - return (False, data) + return (False, None) class WorkersAdminRequest(AdminRequest): @@ -2279,7 +2284,7 @@ class ServerAdminRequest(AdminRequest): x = end_index_newline + 1 return (True, data[x:]) else: - return (False, data) + return (False, None) class NonBlockingConnection(Connection): |