Hi, I'm using an older copy of SQLObject but sqlobject/cache.py hasn't really changed in 2 years, so this applies to current and past versions.
I operate a website that runs around 4million requests a day through an application using SQLObject. At about mid day I end up with large amount of weakref objects and slowing response times. Top 6 objects in memory: 2887448 <type 'weakref'> 209963 <type 'dict'> 68189 <type 'tuple'> 45584 <type 'weakproxy'> 45584 <class 'sqlobject.main.SQLObjectState'> 45584 <class 'sqlobject.declarative.sqlmeta'> These objects are from the CacheFactory.expiredCache dictionary that holds weak references to SQLObject instances by id. Some of these dictionaries reach ~1.5 million keys, each SQLObject.get() request has to look into this dictionary which results in an access slowdown and memory growth. When the object behind the weak reference is collected, a weakref with a dead object is left in the cache, In my case this is a memory leak. Any comments or improvements on this method are appreciated. There are lots of ways to solve this problem but I think this is the least disruptive. Weakref callbacks can't be used because the "release" callback happens in the cull method. I do 2 things in the cull method 1 - cull dead weak references out of the expiredCache. 2 - avoid placing dead weak references into the expiredCache def cull(self): """ Runs through the cache and expires objects. E.g., if ``cullFraction`` is 3, then every third object is moved to the 'expired' (aka weakref) cache. """ self.lock.acquire() try: #remove dead references from the expired cache keys = self.expiredCache.keys() for key in keys: if self.expiredCache[key]() is None: self.expiredCache.pop(key, None) keys = self.cache.keys() for i in xrange(self.cullOffset, len(keys), self.cullFraction): id = keys[i] # create a weakref, then remove from the cache obj = ref(self.cache[id]) del self.cache[id] #the object may have been gc'd when removed from the cache #above, no need to place in expiredCache if obj() is not None: self.expiredCache[id] = obj # This offset tries to balance out which objects we # expire, so no object will just hang out in the cache # forever. self.cullOffset = (self.cullOffset + 1) % self.cullFraction finally: self.lock.release() Thanks, Jason ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ sqlobject-discuss mailing list sqlobject-discuss@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss