From 74d0de691a592dcbd4cb1695d2ed4e8592315002 Mon Sep 17 00:00:00 2001 From: Eugene Oden Date: Tue, 23 Feb 2010 16:38:59 -0500 Subject: [PATCH] changed the BaseHub timer list management to use heapq instead of bisect better overall performance (especially for many outstanding timers) new benchmark --- benchmarks/hub_timers.py | 41 ++++++++++++++++++++++++++++++++++++++++ eventlet/hubs/hub.py | 24 ++++++++++++++++------- 2 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 benchmarks/hub_timers.py diff --git a/benchmarks/hub_timers.py b/benchmarks/hub_timers.py new file mode 100644 index 0000000..1df7386 --- /dev/null +++ b/benchmarks/hub_timers.py @@ -0,0 +1,41 @@ +#! /usr/bin/env python + +# test timer adds & expires on hubs.hub.BaseHub + +import sys +import eventlet +import random +import time +from eventlet.hubs import timer, get_hub + +timer_count = 100000 + +if len(sys.argv) >= 2: + timer_count = int(sys.argv[1]) + +l = [] + +def work(n): + l.append(n) + +timeouts = [random.uniform(0, 10) for x in xrange(timer_count)] + +hub = get_hub() + +start = time.time() + +scheduled = [] + +for timeout in timeouts: + t = timer.Timer(timeout, work, timeout) + t.schedule() + + scheduled.append(t) + +hub.prepare_timers() +hub.fire_timers(time.time()+11) +hub.prepare_timers() + +end = time.time() + +print "Duration: %f" % (end-start,) diff --git a/eventlet/hubs/hub.py b/eventlet/hubs/hub.py index c5e885e..90a1ad7 100644 --- a/eventlet/hubs/hub.py +++ b/eventlet/hubs/hub.py @@ -1,4 +1,4 @@ -import bisect +import heapq import sys import traceback @@ -196,10 +196,10 @@ class BaseHub(object): self.timer_finished(timer) def prepare_timers(self): - ins = bisect.insort_right + heappush = heapq.heappush t = self.timers for item in self.next_timers: - ins(t, item) + heappush(t, item) del self.next_timers[:] def schedule_call_local(self, seconds, cb, *args, **kw): @@ -229,10 +229,21 @@ class BaseHub(object): def fire_timers(self, when): t = self.timers - last = bisect.bisect_right(t, (when, 1)) + heappop = heapq.heappop + i = 0 - for i in xrange(last): - timer = t[i][2] + + while t: + next = t[0] + + exp = next[0] + timer = next[2] + + if when < exp: + break + + heappop(t) + try: try: timer() @@ -242,7 +253,6 @@ class BaseHub(object): self.squelch_timer_exception(timer, sys.exc_info()) finally: self.timer_finished(timer) - del t[:last] # for debugging: