From: "David A. Black" Date: 2005-10-10T00:20:34+09:00 Subject: Re: using lambda/Proc can prevent a lot of garbage collection Hi -- On Sun, 9 Oct 2005, Eric Mahurin wrote: > 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 That's an interesting illustration, but I don't think I'd call it a memory leak, since it's working as advertised. (At least, "memory leak" to me implies something going wrong under the hood, so to speak.) > 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. Nooooo...please... not *another* Proc/proc/lambda/block/method-like object :-) > 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. It would be great if such things could be optimized away, but I just can't reconcile doing it by "stingy" binding at the expense of the dynamic techniques normally available. Maybe we all just have to be aware of the fact that returning a closure means, in a sense, not returning. David -- David A. Black dblack@wobblini.net