diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-07-13 16:28:42 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-07-13 16:29:07 -0400 |
| commit | 731a4daf63dc0fdb784d195e89c5f357420657fb (patch) | |
| tree | 274bd30f51930e070c086b9a8cc34b4e41b52547 /lib/sqlalchemy/orm/state.py | |
| parent | fd8b2d188c58626bdc0d2f11341bc99ba81ae91d (diff) | |
| download | sqlalchemy-731a4daf63dc0fdb784d195e89c5f357420657fb.tar.gz | |
A performance fix related to the usage of the :func:`.defer` option
when loading mapped entities. The function overhead of applying
a per-object deferred callable to an instance at load time was
significantly higher than that of just loading the data from the row
(note that ``defer()`` is meant to reduce DB/network overhead, not
necessarily function call count); the function call overhead is now
less than that of loading data from the column in all cases. There
is also a reduction in the number of "lazy callable" objects created
per load from N (total deferred values in the result) to 1 (total
number of deferred cols).
[ticket:2778]
Diffstat (limited to 'lib/sqlalchemy/orm/state.py')
| -rw-r--r-- | lib/sqlalchemy/orm/state.py | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py index 6ade91b3e..c479d880d 100644 --- a/lib/sqlalchemy/orm/state.py +++ b/lib/sqlalchemy/orm/state.py @@ -305,14 +305,19 @@ class InstanceState(interfaces._InspectionAttr): dict_.pop(key, None) self.callables[key] = self - def _set_callable(self, dict_, key, callable_): - """Remove the given attribute and set the given callable - as a loader.""" - - old = dict_.pop(key, None) - if old is not None and self.manager[key].impl.collection: - self.manager[key].impl._invalidate_collection(old) - self.callables[key] = callable_ + @classmethod + def _row_processor(cls, manager, fn, key): + impl = manager[key].impl + if impl.collection: + def _set_callable(state, dict_, row): + old = dict_.pop(key, None) + if old is not None: + impl._invalidate_collection(old) + state.callables[key] = fn + else: + def _set_callable(state, dict_, row): + state.callables[key] = fn + return _set_callable def _expire(self, dict_, modified_set): self.expired = True @@ -359,7 +364,7 @@ class InstanceState(interfaces._InspectionAttr): self.manager.dispatch.expire(self, attribute_names) - def __call__(self, passive): + def __call__(self, state, passive): """__call__ allows the InstanceState to act as a deferred callable for loading expired attributes, which is also serializable (picklable). |
