summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames E. Blair <jeblair@redhat.com>2016-07-17 08:05:57 -0700
committerJames E. Blair <jeblair@redhat.com>2016-07-17 08:05:57 -0700
commit2defbeaa1beb9ff9e0e3e31529f1f761ac4fcae5 (patch)
tree1beac6df51d10f8f6a2da9b2d99e3d6d1d124d83
parent550873b76abded12cd27c054b0dab0511ffd5e36 (diff)
downloadgear-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__.py19
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):