From fb639dc79e1118e453a2df43e11b719753e1aa69 Mon Sep 17 00:00:00 2001 From: Dmitry Volodin Date: Thu, 26 May 2016 02:17:38 +0400 Subject: [PATCH] _Timeout.__lt__ speedup One of our services uses a lots of callbacks (~15k per IOLoop) and performs massive network IO. During profiling we'd found that significant amount of time consumed in the _Timeout.__lt__ method. Current implementation constantly builds two tuples per comparison. Proposed one pre-builds tuple during _Timeout creation. Its about ~40% faster. In [1]: from tornado.ioloop import _Timeout, IOLoop In [2]: io = IOLoop.current() In [3]: t0 = _Timeout(io.time(), None, io) In [4]: t1 = _Timeout(io.time(), None, io) In [5]: %timeit t0 < t1 1000000 loops, best of 3: 587 ns per loop In [6]: %timeit t0 < t1 1000000 loops, best of 3: 336 ns per loop --- tornado/ioloop.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tornado/ioloop.py b/tornado/ioloop.py index 0bcbd776..d73e2712 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -966,26 +966,24 @@ class _Timeout(object): """An IOLoop timeout, a UNIX timestamp and a callback""" # Reduce memory overhead when there are lots of pending callbacks - __slots__ = ['deadline', 'callback', 'tiebreaker'] + __slots__ = ['deadline', 'callback', 'tdeadline'] def __init__(self, deadline, callback, io_loop): if not isinstance(deadline, numbers.Real): raise TypeError("Unsupported deadline %r" % deadline) self.deadline = deadline self.callback = callback - self.tiebreaker = next(io_loop._timeout_counter) + self.tdeadline = (deadline, next(io_loop._timeout_counter)) # Comparison methods to sort by deadline, with object id as a tiebreaker # to guarantee a consistent ordering. The heapq module uses __le__ # in python2.5, and __lt__ in 2.6+ (sort() and most other comparisons # use __lt__). def __lt__(self, other): - return ((self.deadline, self.tiebreaker) < - (other.deadline, other.tiebreaker)) + return self.tdeadline < other.tdeadline def __le__(self, other): - return ((self.deadline, self.tiebreaker) <= - (other.deadline, other.tiebreaker)) + return self.tdeadline <= other.tdeadline class PeriodicCallback(object):