A
Ara.T.Howard
Just because a process frees all its memory before it > terminates doesn't
mean there isn't a leak. That doesn't help too much if you run out of
memory before the process is done. I've seen 2 definitions: a) when a
program isn't freeing memory that isn't used anymore, b) when a program
loses all references to memory that isn't being freed. From the ruby script
level for this example, by both of these definitions it is a memory leak.
From ruby itself, ruby probably still has references to the memory, so (b)
may not call it a "memory leak". To me (a) is the right definition because
it describes symtoms not the mechanism. If any program keeps growing in
memory and it shouldn't, I'd say it has a memory leak. It doesn't matter
how it comes about and whether or not the program could free the memory if
it was fixed, it is still "leaking" memory.
by your definition the code i was working with last week is 'leaky': it
malloc's an 4GB grid (yes that's right) and does nearest neighbor filling on
it. if you think about it for a few moments you'll realize that only a small
window of pixels needs to be in memory at once and, after a pixel has been
written it will never be needed again, except very soon after as a neighbor
itself, thus it need not remain in memory. the code didn't run - it ran out of
memory. there is not leak, just too large a memory requirement. changing the
malloc/write/free to mmap/munmap fixed the problem - proving there was no leak
since allocating/deallocating a different way allowed the code to run and
recognizing that the code had not lost the ability (pointer) to free the
memory, it just hadn't yet.
they key to 'a' above is "isn't used anymore." all ruby knows is that your
proc __might__ need __anything__, for instance:
harp:~ > cat a.rb
def scope
a, b = 4, 2
lambda{|s| eval "p #{ s }" }
end
scope[ ARGV.shift ]
harp:~ > ruby a.rb a
4
harp:~ > ruby a.rb b
2
so it must, according the present promised behaviour of lambda, preverse
everything. so it seems that it cannot be a leak according to 'a' because it's
t.b.d if the memory will be used or not and it cannot be a leak according to
'b' because references are clearly not lost. an interpreter cannot manage
memory as efficiently as a very bright programmer - it can do it better than
most though.
fork/drb/ and co-processes are good tools for cases like this. it's easy to
setup a memory sandbox in ruby that you can pass and return objects from and
which is guarunteed to free all memory (on exit).
in any case, it seems the issue is that people may not always like what lambda
does, but it seems like it's doing it properly.
If you want to assign blame to ruby, the problem is not GC.
The problem is that closures hold strong references to all
variables in the scope whether or not they are used. One of my
solutions was to make references (in Proc#binding) to currently
unused variables (by the closure) "weak", so that they wouldn't
prevent GC.
agreed - but no 'leak'.
cheers.
-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| anything that contradicts experience and logic should be abandoned.
| -- h.h. the 14th dalai lama
===============================================================================