From: Tom S. <tsc...@li...> - 2000-12-04 16:21:59
|
Geoff Talvola wrote: > > Tom Schwaller wrote: > > > WOW. Still very good compared to the same Zope example (I even > > did a loop (for in in range(15)...) and still got amazing resultas > > on my Dual Celeron, 256 MB RAM maschine). Unfortunately under > > this heavy load I also got the following exception: > > > > Traceback (innermost last): > > File "Application.py", line 283, in dispatchRequest > > self.handleGoodURL(transaction) > > File "Application.py", line 382, in handleGoodURL > > self.respond(transaction) > > File "Application.py", line 455, in respond > > transaction.respond() > > File "Transaction.py", line 93, in respond > > self._servlet.respond(self) > > File "HTTPServlet.py", line 38, in respond > > method(self, trans) > > File "Page.py", line 33, in respondToGet > > self._respond(transaction) > > File "Page.py", line 52, in _respond > > self.writeHTML() > > File "Page.py", line 100, in writeHTML > > self.writeBody() > > File "SidebarPage.py", line 56, in writeBody > > self.writeContent() > > File "Examples/DB.py", line 10, in writeContent > > db = pool.getConnection() > > File "Cans/DBPool.py", line 53, in _threadsafe_getConnection > > con = PooledConnection(self, self.connections[self.nextCon]) > > IndexError: list index out of range > > > > There seems to be a problem in the proposed implementation. > > I guess, it should allocate 5 connections and use them > > as before, but under heavy load it should allocate 5 more > > conections (and 5 more,...) when necessary. Anybody this kind > > of improvements at hand? Generally > > Looks like _threadsafe_getConnection is not itself thread-safe. Ironically, the "unthreadsafe" version looks > thread-safe :-) > > One way to fix it is to use a Lock object. Add > > self.lock = threading.Lock() > > to the "elif dbModule.threadsafety >= 2:" part of __init__, then change _threadsafe_getConnection() to > (untested): > > def _threadsafe_getConnection(self): > self.lock.acquire() > try: > con = PooledConnection(self, self.connections[self.nextCon]) > self.nextCon = self.nextCon + 1 > if self.nextCon >= len(self.connections): > self.nextCon = 0 > return con > finally: > self.lock.release() > We just had a discussion here about that problem and came to the same solution, so it's very recomforting to see your code here :-) thanks a lot. Seems to work nicely... Performancewise the following Code is as fast as the connection pooling example, but threads can produce inpredictably many connections if necessary.. from ExamplePage import ExamplePage import MySQLdb class DB1(ExamplePage): def __init__(self): ExamplePage.__init__(self) print 'connection1' self._db=MySQLdb.connect(user='...', passwd='...', db='...', unix_socket='/var/lib/mysql/mysql.sock') def writeContent(self): self.writeln('<P>Welcome to the DBPooling example!</P>') cursor = self._db.cursor() # can put that in __ init__ too cursor.execute("SELECT realname FROM users WHERE userid < 25") for realname in cursor.fetchall(): self.writeln('%s<br>' % realname) def __del__(self): self._db.close() Even getting a connection in writeContent has the same performance, but this is a MySQL feature. Other databases need much more time for the connection.. Is this code ready for CVS or will there be other under the hood MySQL-mechanisms in MiddleKit? -- Tom Schwaller http://www.linux-community.de http://www.linux-magazin.de |