From: Eric Mahurin Date: 2005-10-09T23:26:19+09:00 Subject: Re: using lambda/Proc can prevent a lot of garbage collection --- Kero wrote: > > Does anybody else think it is a serious issue that a Proc > holds > > references to all variables (including self) where it was > > created (through a block)? These references are held > through > > Proc#binding. Although this does add some useful > capability on > > occasion, this causes excess memory to be used (worst case > > could be a leaky program). Is this worth it? Personally, > I > > think not. I'd propose that Proc#binding return something > that > > only have access to variables referenced in the Proc. Even > the > > self from the defining context would be prohibited if not > > referenced (possibly implicitly) in the Proc. Another > option > > would be to make these references weak so that they won't > > prevent GC and those references would disappear if the > > referenced object (including the variables/variable-table) > is > > GCed. > > Which variables does a proc reference, when it uses eval, > looks things > up via symbols, etc, etc? > > You can't know in advance. > > For an editor (or irb/completion) a best effort approach is > OK, for a > binding, it is not OK. Here is an example where a Proc can cause a memory leak: ruby -e ' n=2**13;squares=(1..n).map{|i|a=(1..i).to_a;lambda{i*i}}; IO.readlines("/proc/#{Process.pid}/status").grep(/VmSize/).display' VmSize: 169312 kB You wouldn't expect each of these lambda's to need the local "a", but the binding holds it. Right now, the programmer needs to specifically think about this and clear these unexpected object references by hand: ruby -e ' n=2**13;squares = (1..n).map{|i|a=(1..i).to_a;f=lambda{i*i};a=nil;f}; IO.readlines("/proc/#{Process.pid}/status").grep(/VmSize/).display' VmSize: 10644 kB To me, it seems kind of silly for the programmer to have to worry about this level of detail. I'd expect most Proc's to not need access to all variables in the defining context. Here are the solutions I see: 1. Let the ruby programmer worry about it. They should assign a variable to nil when a Proc has access to it and they are done needing the variable. 2. Proc#binding should give a binding that only has variables that the block accesses (determined when the compiled). 3. Proc#binding should hold weak references to variables that the block doesn't access (at compile-time). 4. Provide an additional facility for generating a Proc-like object that doesn't have full variable access to the surrounding context like a Proc has. This could be an Proc method that generates a new Proc-like object, a Proc method modifies self in-place, a different block syntax, or something else. Personally, I think #2 or #3 should be done, because it is automatic, but this will could cause code that does eval within the block or from Proc#binding to break - as Kero said. __________________________________ Yahoo! Music Unlimited Access over 1 million songs. Try it free. http://music.yahoo.com/unlimited/