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.
···
--- Kero <kero@chello.single-dot.nl> 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.
__________________________________
Yahoo! Music Unlimited
Access over 1 million songs. Try it free.
http://music.yahoo.com/unlimited/