From 48af3d33226a8f432b50e3ff9b54c59c2d9e4cda Mon Sep 17 00:00:00 2001 From: Vijay Pandurangan Date: Sat, 19 Nov 2011 15:59:38 -0800 Subject: remove unnecessary copies when only one handler matches. This was taking up ~ 15% of CPU on moderate load. --- sleekxmpp/xmlstream/xmlstream.py | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'sleekxmpp/xmlstream/xmlstream.py') diff --git a/sleekxmpp/xmlstream/xmlstream.py b/sleekxmpp/xmlstream/xmlstream.py index 7b941bf7..1453a2a1 100644 --- a/sleekxmpp/xmlstream/xmlstream.py +++ b/sleekxmpp/xmlstream/xmlstream.py @@ -873,20 +873,25 @@ class XMLStream(object): event queue. All event handlers will run in the same thread. """ - for handler in self.__event_handlers.get(name, []): + handlers = self.__event_handlers.get(name, []) + for handler in handlers: + #TODO: Data should not be copied, but should be read only, + # but this might break current code so it's left for future. + + out_data = copy.copy(data) if len(handlers) > 1 else data + old_exception = getattr(data, 'exception', None) if direct: try: - handler[0](copy.copy(data)) + handler[0](out_data) except Exception as e: error_msg = 'Error processing event handler: %s' log.exception(error_msg , str(handler[0])) - if hasattr(data, 'exception'): - data.exception(e) + if old_exception: + old_exception(e) else: self.exception(e) else: - self.event_queue.put(('event', handler, copy.copy(data))) - + self.event_queue.put(('event', handler, out_data)) if handler[2]: # If the handler is disposable, we will go ahead and # remove it now instead of waiting for it to be @@ -1201,17 +1206,17 @@ class XMLStream(object): # to run "in stream" will be executed immediately; the rest will # be queued. unhandled = True - for handler in self.__handlers: - if handler.match(stanza): - stanza_copy = copy.copy(stanza) - handler.prerun(stanza_copy) - self.event_queue.put(('stanza', handler, stanza_copy)) - try: - if handler.check_delete(): - self.__handlers.remove(handler) - except: - pass # not thread safe - unhandled = False + matched_handlers = filter(lambda h: h.match(stanza), self.__handlers) + for handler in matched_handlers: + stanza_copy = copy.copy(stanza) if len(matched_handlers) > 1 else stanza + handler.prerun(stanza_copy) + self.event_queue.put(('stanza', handler, stanza_copy)) + try: + if handler.check_delete(): + self.__handlers.remove(handler) + except: + pass # not thread safe + unhandled = False # Some stanzas require responses, such as Iq queries. A default # handler will be executed immediately for this case. -- cgit v1.2.3