summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/event
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-01-04 19:05:31 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2015-01-04 19:05:31 -0500
commitb3bf7915b59c9c749d335984e03b386605516d0f (patch)
tree50634f8743e9e52a4541ec8649cc352678217c5c /lib/sqlalchemy/event
parent46a35b7647ac9213a2d968e74b50ca070f30abe2 (diff)
downloadsqlalchemy-b3bf7915b59c9c749d335984e03b386605516d0f.tar.gz
- scale back _Dispatch and _JoinedDispatcher to use a __getitem__ scheme
to start up listener collections; this pulls the overhead off of construction and makes performance much like the descriptor version, while still allowing slots. Fix up some profiles.
Diffstat (limited to 'lib/sqlalchemy/event')
-rw-r--r--lib/sqlalchemy/event/base.py41
1 files changed, 29 insertions, 12 deletions
diff --git a/lib/sqlalchemy/event/base.py b/lib/sqlalchemy/event/base.py
index 962d850c2..2d5468886 100644
--- a/lib/sqlalchemy/event/base.py
+++ b/lib/sqlalchemy/event/base.py
@@ -67,23 +67,35 @@ class _Dispatch(object):
# in one ORM edge case, an attribute is added to _Dispatch,
# so __dict__ is used in just that case and potentially others.
- __slots__ = '_parent', '_instance_cls', '__dict__'
+ __slots__ = '_parent', '_instance_cls', '__dict__', '_empty_listeners'
- _empty_listeners = weakref.WeakKeyDictionary()
+ _empty_listener_reg = weakref.WeakKeyDictionary()
def __init__(self, parent, instance_cls=None):
self._parent = parent
self._instance_cls = instance_cls
if instance_cls:
try:
- _empty_listeners = self._empty_listeners[instance_cls]
+ self._empty_listeners = self._empty_listener_reg[instance_cls]
except KeyError:
- _empty_listeners = self._empty_listeners[instance_cls] = [
- _EmptyListener(ls, instance_cls)
- for ls in parent._event_descriptors
- ]
- for ls in _empty_listeners:
- setattr(self, ls.name, ls)
+ self._empty_listeners = \
+ self._empty_listener_reg[instance_cls] = dict(
+ (ls.name, _EmptyListener(ls, instance_cls))
+ for ls in parent._event_descriptors
+ )
+ else:
+ self._empty_listeners = {}
+
+ def __getattr__(self, name):
+ # assign EmptyListeners as attributes on demand
+ # to reduce startup time for new dispatch objects
+ try:
+ ls = self._empty_listeners[name]
+ except KeyError:
+ raise AttributeError(name)
+ else:
+ setattr(self, ls.name, ls)
+ return ls
@property
def _event_descriptors(self):
@@ -244,9 +256,14 @@ class _JoinedDispatcher(object):
self.local = local
self.parent = parent
self._instance_cls = self.local._instance_cls
- for ls in local._event_descriptors:
- setattr(self, ls.name, _JoinedListener(
- parent, ls.name, ls))
+
+ def __getattr__(self, name):
+ # assign _JoinedListeners as attributes on demand
+ # to reduce startup time for new dispatch objects
+ ls = getattr(self.local, name)
+ jl = _JoinedListener(self.parent, ls.name, ls)
+ setattr(self, ls.name, jl)
+ return jl
@property
def _listen(self):