From: Mike Bayer Date: Wed, 22 Aug 2007 19:14:30 +0000 (+0000) Subject: restored WeakValueDict for threadlocal connections + profiler test, addressing X-Git-Tag: rel_0_4beta4~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e755e90681b4059c2636e34a4d4f0ace1f4ef387;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git restored WeakValueDict for threadlocal connections + profiler test, addressing [ticket:754] --- diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py index 8802337ea7..a80502df0f 100644 --- a/lib/sqlalchemy/pool.py +++ b/lib/sqlalchemy/pool.py @@ -115,7 +115,10 @@ class Pool(object): def __init__(self, creator, recycle=-1, echo=None, use_threadlocal=True, listeners=None): self.logger = logging.instance_logger(self, echoflag=echo) - self._threadconns = {} + # the WeakValueDictionary works more nicely than a regular dict + # of weakrefs. the latter can pile up dead reference objects which don't + # get cleaned out. WVD adds from 1-6 method calls to a checkout operation. + self._threadconns = weakref.WeakValueDictionary() self._creator = creator self._recycle = recycle self._use_threadlocal = use_threadlocal @@ -153,10 +156,10 @@ class Pool(object): return _ConnectionFairy(self).checkout() try: - return self._threadconns[thread.get_ident()]().checkout() + return self._threadconns[thread.get_ident()].checkout() except KeyError: agent = _ConnectionFairy(self) - self._threadconns[thread.get_ident()] = weakref.ref(agent) + self._threadconns[thread.get_ident()] = agent return agent.checkout() def return_conn(self, record): diff --git a/test/profiling/alltests.py b/test/profiling/alltests.py index 94f7e1fd20..21e1b3578e 100644 --- a/test/profiling/alltests.py +++ b/test/profiling/alltests.py @@ -5,6 +5,7 @@ import unittest def suite(): modules_to_test = ( 'profiling.compiler', + 'profiling.pool', ) alltests = unittest.TestSuite() for name in modules_to_test: diff --git a/test/profiling/pool.py b/test/profiling/pool.py new file mode 100644 index 0000000000..f113644638 --- /dev/null +++ b/test/profiling/pool.py @@ -0,0 +1,40 @@ +import testbase +from sqlalchemy import * +from testlib import * +from sqlalchemy.pool import QueuePool +from sqlalchemy.databases import sqlite + +class QueuePoolTest(AssertMixin): + def setUp(self): + global pool + pool = QueuePool(creator = lambda: sqlite.SQLiteDialect.dbapi().connect(':memory:'), pool_size = 3, max_overflow = -1, use_threadlocal = True) + + # the WeakValueDictionary used for the pool's "threadlocal" idea adds 1-6 method calls to each of these. + # however its just a lot easier stability wise than dealing with a strongly referencing dict of weakrefs. + # [ticket:754] immediately got opened when we tried a dict of weakrefs, and though the solution there + # is simple, it still doesn't solve the issue of "dead" weakrefs sitting in the dict taking up space + + @profiling.profiled('pooltest_connect', call_range=(40, 45), always=True) + def test_first_connect(self): + conn = pool.connect() + + def test_second_connect(self): + conn = pool.connect() + conn.close() + + @profiling.profiled('pooltest_second_connect', call_range=(24, 24), always=True) + def go(): + conn2 = pool.connect() + return conn2 + c2 = go() + + def test_second_samethread_connect(self): + conn = pool.connect() + + @profiling.profiled('pooltest_samethread_connect', call_range=(4, 4), always=True) + def go(): + return pool.connect() + c2 = go() + +if __name__ == '__main__': + testbase.main()