[Zope-dev] Re: Catalog performance

John Barratt jlb at ball.langarson.com.au
Thu Sep 11 13:03:42 EDT 2003


Simon Michael wrote:

 > John Barratt wrote:
 >
 >> the problem (which seems likely) then you can ghostify the objects
 >> that were ghosts to begin with, and it will save memory (unless all
 >> those objects are already in cache).
 >
 >
 > This is rather interesting, but I don't quite follow what's happening.
 > If  you can say a little more, or suggest a doc reference, I'm all ears.

In general when an object is first loaded from the ZODB it is in a 
'ghost' state, and is only a shell, it has no attributes etc.  When you 
access (almost) any attribute on that object (eg. do : value = ob.attr), 
it gets activated (the contents are loaded automatically, and then the 
value returned).  This is when the real memory usage takes place.

So if you get an object from the ZODB and don't access any attributes, 
it will remain in a ghosted state.  Some core python attributes *don't* 
cause it to activate such as accessing __dict__, and also clearly the 
reserved persistent _p_* attributes.

If you look at the Cache Paramaters tab of your Database in the Control 
Panel (at least with Zope 2.6.2, perhaps 2.6.1) you can see how many 
objects are in memory, and how many are just 'ghosts'.  I think ghosts 
are only 'removed' after a restart, and essentially just contain a 
_p_oid that references the object in the ZODB, ready for re-activation.

A general reference for the ZODB can be found here that explains more :

http://www.python.org/workshops/2000-01/proceedings/papers/fulton/zodb3.html

An example use (and good discussion) that is similar, can be found at 
the link below.  I found this after having problems with objects not 
de-ghostifying properly when just accessing __dict__ :

http://aspn.activestate.com/ASPN/Mail/Message/zodb-dev/913762

Also a grep through the zope source code & some products will also find 
many examples of 'deactivating' objects after a 'walk' :

eg. From OFS.ObjectManager :
     def manage_afterAdd(self, item, container):
         for object in self.objectValues():
             try: s=object._p_changed
             except: s=0
             if hasattr(aq_base(object), 'manage_afterAdd'):
                 object.manage_afterAdd(item, container)
             if s is None: object._p_deactivate()

A change to my example code that would be advisable is the wrapping of 
the _p_changed test in a try/except incase the object is None, or for 
some reason isn't persistent, and hence doesn't have a _p_changed.

I hope this helps & makes sense!

Cheers,

JB.





More information about the Zope-Dev mailing list