From: Robert Klemme Date: 2007-04-23T22:25:07+09:00 Subject: Re: Tracking down a garbage collection problem On 23.04.2007 11:03, Wincent Colaiuta wrote: > On 21 abr, 16:50, Robert Klemme wrote: >> I don't know what techniques exactly you employ but it seems indeed that >> the cached data is held on to longer than intended. >> >>> As this is a largish, complicated project I don't even know where to >>> begin to start investigating this. So really, I am looking for general >>> information on techniques for measuring and exploring memory use and >>> garbage collection in Ruby. >> I am not sure, there might be an extension around. Did you check with >> the RAA? >> >> What I'd do here is a) code inspection b) create a finalizer with some >> debugging output for your cache instance and see whether you see the >> output. If not, you know that your cache instance is still referred to. > > Thanks, Robert. That is excellent advice. The method in question looks > basically like this: > > def parse > # do stuff > cache = MemoizingCache.new > # do more stuff > end > > I changed this to read as follows: > > def parse > # do stuff > cache = MemoizingCache.new > $stderr.print "New cache id #{cache.object_id}\n" > ObjectSpace.define_finalizer(cache, lambda { |id| $stderr.print > "Finalizer for id #{id}\n"}) > # do more stuff > end > > And have confirmed that the cache finalizers are not being called. I > haven't found out how the reference to the local "cache" variable is > being kept alive even after it falls out of scope, but you've given me > the tool necessary to at least find out what's happening. Careful! As Guy pointed out your code basically locks cache in memory itself. You should rather do something like this: def create_finalizer_for(id) lambda { puts "Final #{id}" } end and use that method to create the finalizer lambda. def parse # do stuff cache = MemoizingCache.new $stderr.print "New cache id #{cache.object_id}\n" ObjectSpace.define_finalizer(cache, create_finalizer(cache.object_id)) # do more stuff end HTH robert