summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-05-19 16:57:14 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2014-05-19 16:57:14 -0400
commit474168bd884792b30b5312a18ad68f2563206952 (patch)
tree2dd8f067a3e9ee1d0417aaad8e77448d41a08ea7 /lib/sqlalchemy
parent460465a8749aecff761e1c81c77d7c23e8672789 (diff)
downloadsqlalchemy-474168bd884792b30b5312a18ad68f2563206952.tar.gz
- some inlining, speed up identity map
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/identity.py78
-rw-r--r--lib/sqlalchemy/orm/loading.py24
-rw-r--r--lib/sqlalchemy/orm/state.py12
3 files changed, 69 insertions, 45 deletions
diff --git a/lib/sqlalchemy/orm/identity.py b/lib/sqlalchemy/orm/identity.py
index a91085d28..f9cd99289 100644
--- a/lib/sqlalchemy/orm/identity.py
+++ b/lib/sqlalchemy/orm/identity.py
@@ -8,8 +8,9 @@ import weakref
from . import attributes
from .. import util
-class IdentityMap(dict):
+class IdentityMap(object):
def __init__(self):
+ self._dict = {}
self._modified = set()
self._wr = weakref.ref(self)
@@ -19,6 +20,11 @@ class IdentityMap(dict):
def add(self, state):
raise NotImplementedError()
+ def _add_unpresent(self, state, key):
+ """optional inlined form of add() which can assume item isn't present
+ in the map"""
+ self.add(state)
+
def update(self, dict):
raise NotImplementedError("IdentityMap uses add() to insert data")
@@ -68,11 +74,9 @@ class IdentityMap(dict):
class WeakInstanceDict(IdentityMap):
- def __init__(self):
- IdentityMap.__init__(self)
def __getitem__(self, key):
- state = dict.__getitem__(self, key)
+ state = self._dict[key]
o = state.obj()
if o is None:
raise KeyError(key)
@@ -80,8 +84,8 @@ class WeakInstanceDict(IdentityMap):
def __contains__(self, key):
try:
- if dict.__contains__(self, key):
- state = dict.__getitem__(self, key)
+ if key in self._dict:
+ state = self._dict[key]
o = state.obj()
else:
return False
@@ -91,25 +95,25 @@ class WeakInstanceDict(IdentityMap):
return o is not None
def contains_state(self, state):
- return dict.get(self, state.key) is state
+ return state.key in self._dict and self._dict[state.key] is state
def replace(self, state):
- if dict.__contains__(self, state.key):
- existing = dict.__getitem__(self, state.key)
+ if state.key in self._dict:
+ existing = self._dict[state.key]
if existing is not state:
self._manage_removed_state(existing)
else:
return
- dict.__setitem__(self, state.key, state)
+ self._dict[state.key] = state
self._manage_incoming_state(state)
def add(self, state):
key = state.key
# inline of self.__contains__
- if dict.__contains__(self, key):
+ if key in self._dict:
try:
- existing_state = dict.__getitem__(self, key)
+ existing_state = self._dict[key]
if existing_state is not state:
o = existing_state.obj()
if o is not None:
@@ -121,13 +125,18 @@ class WeakInstanceDict(IdentityMap):
return
except KeyError:
pass
- dict.__setitem__(self, key, state)
+ self._dict[key] = state
self._manage_incoming_state(state)
+ def _add_unpresent(self, state, key):
+ # inlined form of add() called by loading.py
+ self._dict[key] = state
+ state._instance_dict = self._wr
+
def get(self, key, default=None):
- state = dict.get(self, key, default)
- if state is default:
+ if key not in self._dict:
return default
+ state = self._dict[key]
o = state.obj()
if o is None:
return default
@@ -170,15 +179,16 @@ class WeakInstanceDict(IdentityMap):
def all_states(self):
if util.py2k:
- return dict.values(self)
+ return self._dict.values()
else:
- return list(dict.values(self))
+ return list(self._dict.values())
def discard(self, state):
- st = dict.get(self, state.key, None)
- if st is state:
- dict.pop(self, state.key, None)
- self._manage_removed_state(state)
+ if state.key in self._dict:
+ st = self._dict[state.key]
+ if st is state:
+ self._dict.pop(state.key, None)
+ self._manage_removed_state(state)
def prune(self):
return 0
@@ -194,34 +204,38 @@ class StrongInstanceDict(IdentityMap):
attributes.instance_state(self[state.key]) is state)
def replace(self, state):
- if dict.__contains__(self, state.key):
- existing = dict.__getitem__(self, state.key)
+ if state.key in self._dict:
+ existing = self._dict[state.key]
existing = attributes.instance_state(existing)
if existing is not state:
self._manage_removed_state(existing)
else:
return
- dict.__setitem__(self, state.key, state.obj())
+ self._dict[state.key] = state.obj()
self._manage_incoming_state(state)
def add(self, state):
if state.key in self:
- if attributes.instance_state(dict.__getitem__(self,
- state.key)) is not state:
+ if attributes.instance_state(self._dict[state.key]) is not state:
raise AssertionError('A conflicting state is already '
'present in the identity map for key %r'
% (state.key, ))
else:
- dict.__setitem__(self, state.key, state.obj())
+ self._dict[state.key] = state.obj()
self._manage_incoming_state(state)
+ def _add_unpresent(self, state, key):
+ # inlined form of add() called by loading.py
+ self._dict[key] = state.obj()
+ state._instance_dict = self._wr
+
def discard(self, state):
- obj = dict.get(self, state.key, None)
- if obj is not None:
+ if state.key in self._dict:
+ obj = self._dict[state.key]
st = attributes.instance_state(obj)
if st is state:
- dict.pop(self, state.key, None)
+ self._dict.pop(state.key, None)
self._manage_removed_state(state)
def prune(self):
@@ -234,7 +248,7 @@ class StrongInstanceDict(IdentityMap):
keepers = weakref.WeakValueDictionary()
keepers.update(self)
- dict.clear(self)
- dict.update(self, keepers)
+ self._dict.clear()
+ self._dict.update(keepers)
self.modified = bool(dirty)
return ref_count - len(self)
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py
index b79ea429c..8fcace9be 100644
--- a/lib/sqlalchemy/orm/loading.py
+++ b/lib/sqlalchemy/orm/loading.py
@@ -84,7 +84,7 @@ def instances(query, cursor, context):
context.progress.pop(context.refresh_state)
statelib.InstanceState._commit_all_states(
- list(context.progress.items()),
+ context.progress.items(),
session.identity_map
)
@@ -319,6 +319,12 @@ def instance_processor(mapper, context, path, adapter,
populate_existing = context.populate_existing or mapper.always_refresh
invoke_all_eagers = context.invoke_all_eagers
+ load_evt = mapper.class_manager.dispatch.load or None
+ refresh_evt = mapper.class_manager.dispatch.refresh or None
+
+ instance_state = attributes.instance_state
+ instance_dict = attributes.instance_dict
+
if mapper.allow_partial_pks:
is_not_primary_key = _none_set.issuperset
else:
@@ -363,8 +369,8 @@ def instance_processor(mapper, context, path, adapter,
instance = session_identity_map.get(identitykey)
if instance is not None:
- state = attributes.instance_state(instance)
- dict_ = attributes.instance_dict(instance)
+ state = instance_state(instance)
+ dict_ = instance_dict(instance)
isnew = state.runid != context.runid
currentload = not isnew
@@ -394,7 +400,7 @@ def instance_processor(mapper, context, path, adapter,
# when eager_defaults is True.
state = refresh_state
instance = state.obj()
- dict_ = attributes.instance_dict(instance)
+ dict_ = instance_dict(instance)
isnew = state.runid != context.runid
currentload = True
loaded_instance = False
@@ -424,13 +430,13 @@ def instance_processor(mapper, context, path, adapter,
else:
instance = mapper.class_manager.new_instance()
- dict_ = attributes.instance_dict(instance)
- state = attributes.instance_state(instance)
+ dict_ = instance_dict(instance)
+ state = instance_state(instance)
state.key = identitykey
# attach instance to session.
state.session_id = context.session.hash_key
- session_identity_map.add(state)
+ session_identity_map._add_unpresent(state, identitykey)
if currentload or populate_existing:
# state is being fully loaded, so populate.
@@ -451,9 +457,9 @@ def instance_processor(mapper, context, path, adapter,
else:
populate_state(state, dict_, row, isnew, only_load_props)
- if loaded_instance:
+ if loaded_instance and load_evt:
state.manager.dispatch.load(state, context)
- elif isnew:
+ elif isnew and refresh_evt:
state.manager.dispatch.refresh(state, context, only_load_props)
elif state in context.partials or state.unloaded or eager_populators:
diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py
index 5be2a657b..768b73c21 100644
--- a/lib/sqlalchemy/orm/state.py
+++ b/lib/sqlalchemy/orm/state.py
@@ -559,12 +559,16 @@ class InstanceState(interfaces._InspectionAttr):
for state, dict_ in iter:
state.committed_state.clear()
- InstanceState._pending_mutations._reset(state)
+
+ # inline of:
+ # InstanceState._pending_mutations._reset(state)
+ state.__dict__.pop('_pending_mutations', None)
callables = state.callables
- for key in list(callables):
- if key in dict_ and callables[key] is state:
- del callables[key]
+ if callables:
+ for key in list(callables):
+ if key in dict_ and callables[key] is state:
+ del callables[key]
if instance_dict and state.modified:
instance_dict._modified.discard(state)