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 /test/aaa_profiling | |
| 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 'test/aaa_profiling')
| -rw-r--r-- | test/aaa_profiling/test_orm.py | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/test/aaa_profiling/test_orm.py b/test/aaa_profiling/test_orm.py index 199b96e5f..6d71468b7 100644 --- a/test/aaa_profiling/test_orm.py +++ b/test/aaa_profiling/test_orm.py @@ -2,7 +2,7 @@ from sqlalchemy.testing import eq_, assert_raises, \ assert_raises_message from sqlalchemy import exc as sa_exc, util, Integer, String, ForeignKey from sqlalchemy.orm import exc as orm_exc, mapper, relationship, \ - sessionmaker, Session + sessionmaker, Session, defer from sqlalchemy import testing from sqlalchemy.testing import profiling from sqlalchemy.testing import fixtures @@ -257,4 +257,56 @@ class MergeBackrefsTest(fixtures.MappedTest): ]: s.merge(a) +class DeferOptionsTest(fixtures.MappedTest): + @classmethod + def define_tables(cls, metadata): + Table('a', metadata, + Column('id', Integer, primary_key=True), + Column('x', String(5)), + Column('y', String(5)), + Column('z', String(5)), + Column('q', String(5)), + Column('p', String(5)), + Column('r', String(5)), + ) + + @classmethod + def setup_classes(cls): + class A(cls.Basic): + pass + + @classmethod + def setup_mappers(cls): + A = cls.classes.A + a = cls.tables.a + mapper(A, a) + + @classmethod + def insert_data(cls): + A = cls.classes.A + s = Session() + s.add_all([ + A(id=i, + **dict((letter, "%s%d" % (letter, i)) for letter in + ['x', 'y', 'z', 'p', 'q', 'r']) + ) for i in range(1, 1001) + ]) + s.commit() + + @profiling.function_call_count(variance=.10) + def test_baseline(self): + # as of [ticket:2778], this is at 39025 + A = self.classes.A + s = Session() + s.query(A).all() + + @profiling.function_call_count(variance=.10) + def test_defer_many_cols(self): + # with [ticket:2778], this goes from 50805 to 32817, + # as it should be fewer function calls than the baseline + A = self.classes.A + s = Session() + s.query(A).options( + *[defer(letter) for letter in ['x', 'y', 'z', 'p', 'q', 'r']]).\ + all() |
