Ruby GC question (MRI, JRuby, etc)

C

Chuck Remes

My basic understanding of the garbage collectors in use by the various Ruby runtimes is that they all search for objects from a "root" memory object. If an object cannot be reached from this root, then it is collected.

Here's a snippet of ruby code. I'm not sure how the GC will treat it.

class Foo
def initialize
@baz = Baz.new
@quxxo = Quxxo.new
end
end

class Bar
def run
Foo.new
nil
end
end

bar = Bar.new
bar.run
bar.run
bar.run


What happens to the instances of Foo created in the call to #run? Since I am not saving them somewhere (e.g. to an array), do they get collected right away?

If the Foo instances get collected, is it safe to assume the Baz and Quxxo instances are being collected at the same time? Does their existence prevent the Foo instance from being collected?

cr
 
K

Kirk Haines

My basic understanding of the garbage collectors in use by the various Ru=
by runtimes is that they all search for objects from a "root" memory object=
If an object cannot be reached from this root, then it is collected.

It depends on the Ruby. JRuby and Rubinius have different garbage
collectors than MRI Ruby.
What happens to the instances of Foo created in the call to #run? Since I=
am not saving them =A0somewhere (e.g. to an array), do they get collected =
right away?

Nothing is ever collected right away in the MRI rubies currently. The
object will exist in memory until a GC cycle runs. Unless a GC cycle
is started manually (GC.start), GC cycles only run when Ruby runs
short on preallocated memory. Take a look at this
http://www.engineyard.com/blog/2010/mri-memory-allocation-a-primer-for-deve=
lopers/
or google on the subject and you'll find a number of articles that
will explain how it works in more detail than you will get in an
email.
If the Foo instances get collected, is it safe to assume the Baz and Quxx=
o instances are being collected at the same time? Does their existence prev=
ent the Foo instance from being collected?

It depends on why you are assuming it. If you have an implementation
that depends on specific garbage collection behaviors or collection in
specific chronologies in order to work right, it is probably not safe
to assume anything. If you are just trying to understand the memory
behavior of your code, and make sure you aren't doing dumb things that
can lead to a memory leak, then yes, it is safe to assume that the Baz
and Quxxo instances will be collected along with the Foo.


Kirk Haines
 
C

Chuck Remes

It depends on the Ruby. JRuby and Rubinius have different garbage
collectors than MRI Ruby.


Nothing is ever collected right away in the MRI rubies currently. The
object will exist in memory until a GC cycle runs. Unless a GC cycle
is started manually (GC.start), GC cycles only run when Ruby runs
short on preallocated memory. Take a look at this
http://www.engineyard.com/blog/2010/mri-memory-allocation-a-primer-for-developers/
or google on the subject and you'll find a number of articles that
will explain how it works in more detail than you will get in an
email.


It depends on why you are assuming it. If you have an implementation
that depends on specific garbage collection behaviors or collection in
specific chronologies in order to work right, it is probably not safe
to assume anything. If you are just trying to understand the memory
behavior of your code, and make sure you aren't doing dumb things that
can lead to a memory leak, then yes, it is safe to assume that the Baz
and Quxxo instances will be collected along with the Foo.

Kirk,

thanks for the pointer to your write-up at engineyard. I'll be sure to read through it.

In the meantime, it looks like I need to save my Foo instances to an array or something similar if I want to make sure that they do NOT get collected until I'm ready.

cr
 
B

Brian Candler

Chuck said:
In the meantime, it looks like I need to save my Foo instances to an
array or something similar if I want to make sure that they do NOT get
collected until I'm ready.

In any case, if you don't keep a reference to them somewhere, then you
can never call any method on them, so the objects are obviously useless
(which is why they are garbage-collected in the first place)
 
C

Chuck Remes

In any case, if you don't keep a reference to them somewhere, then you
can never call any method on them, so the objects are obviously useless
(which is why they are garbage-collected in the first place)

Not necessarily true. The Bar class in my example could have its own internal lifecycle where it is generating events for Baz and Quxxo which in turn are reacting to or generating events for Bar. Plus, they all may be interacting with yet more objects on a local or remote system. Retaining a reference to the Bar instance from Foo does not preclude them from doing useful work.

cr
 
B

Brian Candler

Chuck said:
Not necessarily true. The Bar class in my example could have its own
internal lifecycle where it is generating events for Baz and Quxxo

Not unless it is running in its own thread. In that case, there will be
a reference to the object held within the thread - for example in a
local variable.

However, if the object exists solely to be shared by DRb, then yes you
will need to keep a handle to it to stop it being garbage-collected.
That's because DRb uses _id2ref to locate objects via just their id.
 
R

Robert Klemme

2010/8/17 Chuck Remes said:
My basic understanding of the garbage collectors in use by the various Ruby runtimes is
that they all search for objects from a "root" memory object. If an object cannot be reached
from this root, then it is collected.

There is a small error in the wording above. While the issue has been
explained already I want to stress this point because this is a
mistake many new to GC make and it explains some weird effects that
special tests show. It should have read

If an object cannot be reached from this root, then it _can be_ collected.

Small change, big difference. :)

Kind regards

robert
 
C

Chuck Remes

There is a small error in the wording above. While the issue has been
explained already I want to stress this point because this is a
mistake many new to GC make and it explains some weird effects that
special tests show. It should have read

If an object cannot be reached from this root, then it _can be_ collected.

Small change, big difference. :)

Ha! Yes, quite true. Depending upon the GC algo in use, some objects may never be collected even though they are eligible for collection.

cr
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top