summaryrefslogtreecommitdiff
path: root/test/aaa_profiling
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-07-13 16:28:42 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2013-07-13 16:29:07 -0400
commit731a4daf63dc0fdb784d195e89c5f357420657fb (patch)
tree274bd30f51930e070c086b9a8cc34b4e41b52547 /test/aaa_profiling
parentfd8b2d188c58626bdc0d2f11341bc99ba81ae91d (diff)
downloadsqlalchemy-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.py54
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()