summaryrefslogtreecommitdiff
path: root/test/perf
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-01-06 20:32:47 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-01-06 20:32:47 +0000
commit1a5ba21076650f085b4583b0d9a862e611b69429 (patch)
tree92415ca7cd90da50b163eda775f4e8620842b1a1 /test/perf
parent4add9d3a0d9b660c9a267827ad3dd4ceceb0bfb5 (diff)
downloadsqlalchemy-1a5ba21076650f085b4583b0d9a862e611b69429.tar.gz
- added a mutex to the mapper compilation step. ive been reluctant to add any kind
of threading anything to SA but this is one spot that its its really needed since mappers are typically "global", and while their state does not change during normal operation, the initial compilation step does modify internal state significantly, and this step usually occurs not at module-level initialization time (unless you call compile()) but at first-request time - added "compile_mappers()" function as a shortcut to compiling all mappers
Diffstat (limited to 'test/perf')
-rw-r--r--test/perf/threaded_compile.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/test/perf/threaded_compile.py b/test/perf/threaded_compile.py
new file mode 100644
index 000000000..3c521f231
--- /dev/null
+++ b/test/perf/threaded_compile.py
@@ -0,0 +1,70 @@
+# tests the COMPILE_MUTEX in mapper compilation
+
+from sqlalchemy import *
+import thread, time, random
+from sqlalchemy.orm import mapperlib
+
+meta = BoundMetaData('sqlite:///foo.db')
+
+t1 = Table('t1', meta,
+ Column('c1', Integer, primary_key=True),
+ Column('c2', String(30))
+ )
+
+t2 = Table('t2', meta,
+ Column('c1', Integer, primary_key=True),
+ Column('c2', String(30)),
+ Column('t1c1', None, ForeignKey('t1.c1'))
+)
+meta.create_all()
+
+class T1(object):
+ pass
+
+class T2(object):
+ pass
+
+class FakeLock(object):
+ def acquire(self):pass
+ def release(self):pass
+
+# uncomment this to disable the mutex in mapper compilation;
+# should produce thread collisions
+#mapperlib._COMPILE_MUTEX = FakeLock()
+
+existing_compile_all = mapperlib.Mapper._compile_all
+state = [False]
+# decorate mapper's _compile_all() method; the mutex in mapper.compile()
+# should insure that this method is only called once by a single thread only
+def monkeypatch_compile_all(self):
+ if state[0]:
+ raise "thread collision"
+ state[0] = True
+ try:
+ print "compile", thread.get_ident()
+ time.sleep(1 + random.random())
+ existing_compile_all(self)
+ finally:
+ state[0] = False
+mapperlib.Mapper._compile_all = monkeypatch_compile_all
+
+def run1():
+ print "T1", thread.get_ident()
+ class_mapper(T1)
+
+def run2():
+ print "T2", thread.get_ident()
+ class_mapper(T2)
+
+for i in range(0,1):
+ clear_mappers()
+ mapper(T1, t1, properties={'t2':relation(T2, backref="t1")})
+ mapper(T2, t2)
+ #compile_mappers()
+ print "START"
+ for j in range(0, 5):
+ thread.start_new_thread(run1, ())
+ thread.start_new_thread(run2, ())
+ print "WAIT"
+ time.sleep(5)
+