Ruby garabage collector

In the "Why's poignant guide to Ruby" book, it states the following:

"If you can't get to an object through a variable, then Ruby will figure
you are done with it and will get rid of it. Periodically, Ruby sends
out its garbage collector to set these objects free."

The point I'm not getting here is: "If you can't get to an object
through a variable..."

Can you provide an examples that illustrates this?

Thanks.

···

--
Posted via http://www.ruby-forum.com/.

The simplest way to think of it is if something falls out of scope.

···

On Jul 13, 2010, at 9:30 AM 7/13/10, Abder-Rahman Ali wrote:

In the "Why's poignant guide to Ruby" book, it states the following:

"If you can't get to an object through a variable, then Ruby will figure
you are done with it and will get rid of it. Periodically, Ruby sends
out its garbage collector to set these objects free."

The point I'm not getting here is: "If you can't get to an object
through a variable..."

Can you provide an examples that illustrates this?

Thanks.
--
Posted via http://www.ruby-forum.com/\.

a = [1,2,3].find {|x| x > 3}

puts a

In this (maybe too simple) example, x is garbage-collected once flow
leaves the block.

···

On 13-07-2010 17:30, Abder-Rahman Ali wrote:

In the "Why's poignant guide to Ruby" book, it states the following:

"If you can't get to an object through a variable, then Ruby will figure
you are done with it and will get rid of it. Periodically, Ruby sends
out its garbage collector to set these objects free."

The point I'm not getting here is: "If you can't get to an object
through a variable..."

Can you provide an examples that illustrates this?

Thanks.

--
http://iruel.net

Abder-Rahman Ali wrote:

In the "Why's poignant guide to Ruby" book, it states the following:

"If you can't get to an object through a variable, then Ruby will figure
you are done with it and will get rid of it. Periodically, Ruby sends
out its garbage collector to set these objects free."

The point I'm not getting here is: "If you can't get to an object
through a variable..."

Can you provide an examples that illustrates this?

Here's an example to play with:

class C; end

def make_one
   $c = C.new
   nil # Can you guess why this is here?
end

def clear!
   $c = nil
end

# How many reachable C instances are there?
# (Note: works in MRI, but maybe not others, such as jruby)
def how_many?
   p ObjectSpace.each_object(C) {}
end

GC.start
how_many? # => 0
make_one
how_many? # => 1
make_one
how_many? # => 2
clear!
how_many? # => 2
GC.start
how_many? # => 0

···

-----

As Rick pointed out ("variables don't get collected, objects do"), the question of variable scope is not really the important one. In the above example, $c is always in scope, because it is a global. What's important is whether an object can be reached from the value assigned to $c.

James Harrison wrote:

The simplest way to think of it is if something falls out of scope.

Thanks James. Can you provide a simple Ruby code to clarify the idea. A
bit confusing me still.

···

--
Posted via http://www.ruby-forum.com/\.

Bruno Antunes wrote:

Thanks.

a = [1,2,3].find {|x| x > 3}

puts a

In this (maybe too simple) example, x is garbage-collected once flow
leaves the block.

Thanks Bruno.

But, I'm always getting as output:
1
2
3

Even if I type {|x| x < 3}

Isn't your program trying to say find the values > 3 ?

In other words, why don't I get some sort of error since I'm requesting
something not here? > 3

Thanks.

···

On 13-07-2010 17:30, Abder-Rahman Ali wrote:

--
Posted via http://www.ruby-forum.com/\.

Actually this is a bad example for several reasons.

1) variables don't get collected, object do.
http://talklikeaduck.denhaven2.com/2006/09/13/on-variables-values-and-objects

  In this example x is a variable which over the course of execution
gets assigned to reference 1, then 2, then 3.

2) FixNums which are the only class of object assigned to x in this
example are never garbage collected, since they are immediate values.

Now what does GC really do? What it really does is make sure that any
object which can still be reached via a chain of references starting
with a root set of references WON"T be freed and reused before they
should be. This is really the primary job of a GC, the secondary job,
which most people think of what a GC does, is to allow the resources
used by objects which be provedn to be no longer be reachable from
that root set to be reused.

The root set comprised references such as:

Any constants in the outermost name space, (e.g. the object which is
referenced by say Array)
Any references currently on the activation stack of running threads.
These references will be things like method invocation parameter
values, local temporary variable values, and block argument values.

The reachable objects are those referenced by any reference in the
root set, any object referenced by any of the variables within those
objects etc. etc.

The effect of a variable going out of scope (e.g. a temporary on the
invocation frame of a method which has returned), is that that
reference is no longer part of the root set. but if there is at least
one other reference to the object in question reachable from somewhere
else in the root set then that object WILL NOT be reclaimed by a
bug-free garbage collector.

···

On Tue, Jul 13, 2010 at 11:40 AM, Bruno A <sardaukar.siet@gmail.com> wrote:

On 13-07-2010 17:30, Abder-Rahman Ali wrote:

In the "Why's poignant guide to Ruby" book, it states the following:

"If you can't get to an object through a variable, then Ruby will figure
you are done with it and will get rid of it. Periodically, Ruby sends
out its garbage collector to set these objects free."

The point I'm not getting here is: "If you can't get to an object
through a variable..."

Can you provide an examples that illustrates this?

Thanks.

a = [1,2,3].find {|x| x > 3}

puts a

In this (maybe too simple) example, x is garbage-collected once flow
leaves the block.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: rubyredrick (Rick DeNatale) · GitHub
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Thanks a lot all.

···

--
Posted via http://www.ruby-forum.com/.

Nothing gets garbage collected here becuase 1,2, and 3 are value objects
(they're special in that they're not stored on the heap, but stored in
the memory that would be the pointer to most other objects), and because
they're still accessible through the array (a points to an array, which
points to each of the array's 3 elements) even after the loop ends.

A better example is:

irb(main):001:0> a=Object.new
=> #<Object:0x7f361c5dbe58>
irb(main):002:0> a=Object.new
=> #<Object:0x7f361c5d1c50>

at the end of this program, there is no longer a variable that points
(either directly or indirectly) to #<Object:0x7f361c5dbe58>, so it can be
garbage collected.

irb(main):003:0> a=
=>
irb(main):004:0> b=Object.new
=> #<Object:0x7f361c5c33d0>
irb(main):005:0> a << b
=> [#<Object:0x7f361c5c33d0>]
irb(main):006:0> b=Object.new
=> #<Object:0x7f361c5a9890>
irb(main):007:0> a << b
=> [#<Object:0x7f361c5c33d0>, #<Object:0x7f361c5a9890>]
irb(main):008:0> b=Object.new
=> #<Object:0x7f361c5941c0>

In this example, nothing gets garbage collected. I allocated three
Objects, and one Array. At the end of execution, the Array is pointed to
by a, and two of the Objects are pointed to by the Array. The third
Object is pointed to by b.

···

On Wed, 14 Jul 2010 00:40:05 +0900, Bruno A wrote:

On 13-07-2010 17:30, Abder-Rahman Ali wrote:

In the "Why's poignant guide to Ruby" book, it states the following:

"If you can't get to an object through a variable, then Ruby will
figure you are done with it and will get rid of it. Periodically, Ruby
sends out its garbage collector to set these objects free."

The point I'm not getting here is: "If you can't get to an object
through a variable..."

Can you provide an examples that illustrates this?

Thanks.

a = [1,2,3].find {|x| x > 3}

puts a

In this (maybe too simple) example, x is garbage-collected once flow
leaves the block.

--
Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

Sure thing. Sounds like you might be new to programming, yeah? Scope is something you may need to look up to understand a little better. In ruby there are a few scope rules that you should look up and get familiar with, and they changed for 1.9.1 in some small ways (I believe...). The MetaProgramming Ruby book has some great insights into scope, too.

Simple, here's an example:

words = ["foo", "bam", "bat"]

words.each do |word| #here we create a variable called "word"
puts "#{word}" #here we print out the contents of the "word" variable
end #here we end the block that word was created inside of

puts "#{word}" #this will fail, as word does not exist outside of the block

word is a variable that is local to the block associated with the .each call on the array. Once the block ends, the variable word stops existing: it "falls out of scope".

Go read up on scoping and scope generally, it'll do you good :wink:

Best

James

···

On Jul 13, 2010, at 9:42 AM 7/13/10, Abder-Rahman Ali wrote:

James Harrison wrote:

The simplest way to think of it is if something falls out of scope.

Thanks James. Can you provide a simple Ruby code to clarify the idea. A
bit confusing me still.

Bruno Antunes wrote:

Thanks.

a = [1,2,3].find {|x| x > 3}

puts a

In this (maybe too simple) example, x is garbage-collected once flow
leaves the block.

Thanks Bruno.

But, I'm always getting as output:
1
2
3

Even if I type {|x| x < 3}

Isn't your program trying to say find the values > 3 ?

In other words, why don't I get some sort of error since I'm requesting
something not here? > 3

Thanks

The point of the example is that x doesn't exist any more outside of the block.

The array correctly returns the output "nil", as no values inside the array are greater than 3. I'm not sure what you're doing wrong: probably a typo somewhere.

metatron:~ james$ irb

a = [1,2,3].find {|x| x > 3}

=> nil

puts a

nil
=> nil

puts x

NameError: undefined local variable or method `x' for main:Object
  from (irb):3

···

On Jul 13, 2010, at 9:59 AM 7/13/10, Abder-Rahman Ali wrote:

On 13-07-2010 17:30, Abder-Rahman Ali wrote:

Ali,

In answer to your original question... I think we got a bit side-tracked by
the mention of 'scope'.

Think of it this way:

As a program executes more and more memory is being written to. This is fine
for a while but if you're the people writing Ruby (or Java even!) you need
to think of a way of somehow stopping the program from eventually wasting
all the memory available to it; or else nobody is going to use it because it
will run out of space all the time!

What they do is look for some memory to 'reuse'. They can't just write over
any old memory because it might still be needed... BUT... suppose they knew
some memory was never going to be needed by the program again - then it can
be safely deleted (and reused). cool.

Now, the question is how do we know some memory is NEVER needed again? Well,
suppose you created an object 'x' (there is memory being used to store x),
but there is now no possible route for the program to take whereby x is
accessed again - we can mark x as 'garbage' and 'collect' back it's
associated memory for reuse.

The implementation of a garbage collector (something that notices x will
never be needed again) is more technical - and there is more than one way to
do it (watching things become out of scope is just one).

You said you were struggling with the statement:

"If you can't get to an object
through a variable..."

That's just another way of saying

'if the memory can be reused' or
'it's impossible for the program to ever need that variable again' or
'the variable (say x) is garbage'!

You have garbage collectors in Java too by the way and C# etc.. just think
of it as a bit of housekeeping that needs doing every now and again
otherwise your program would grind to a halt because there would be nowhere
left to add new objects!

It is still possible that a program can run out of memory.. did you ever see
an OutOfMemoryError in Java? the garbage collector will do it's best but if
your program is still using a load of memory it has no option but to blow up
:slight_smile:

···

On Tue, Jul 13, 2010 at 11:13 PM, Abder-Rahman Ali < abder.rahman.ali@gmail.com> wrote:

Thanks a lot all.
--
Posted via http://www.ruby-forum.com/\.

I stand corrected. Thanks!

···

On 14-07-2010 4:08, Ken Bloom wrote:

On Wed, 14 Jul 2010 00:40:05 +0900, Bruno A wrote:

On 13-07-2010 17:30, Abder-Rahman Ali wrote:

In the "Why's poignant guide to Ruby" book, it states the following:

"If you can't get to an object through a variable, then Ruby will
figure you are done with it and will get rid of it. Periodically, Ruby
sends out its garbage collector to set these objects free."

The point I'm not getting here is: "If you can't get to an object
through a variable..."

Can you provide an examples that illustrates this?

Thanks.

a = [1,2,3].find {|x| x > 3}

puts a

In this (maybe too simple) example, x is garbage-collected once flow
leaves the block.

Nothing gets garbage collected here becuase 1,2, and 3 are value objects
(they're special in that they're not stored on the heap, but stored in
the memory that would be the pointer to most other objects), and because
they're still accessible through the array (a points to an array, which
points to each of the array's 3 elements) even after the loop ends.

A better example is:

irb(main):001:0> a=Object.new
=> #<Object:0x7f361c5dbe58>
irb(main):002:0> a=Object.new
=> #<Object:0x7f361c5d1c50>

at the end of this program, there is no longer a variable that points
(either directly or indirectly) to #<Object:0x7f361c5dbe58>, so it can be
garbage collected.

irb(main):003:0> a=
=>
irb(main):004:0> b=Object.new
=> #<Object:0x7f361c5c33d0>
irb(main):005:0> a << b
=> [#<Object:0x7f361c5c33d0>]
irb(main):006:0> b=Object.new
=> #<Object:0x7f361c5a9890>
irb(main):007:0> a << b
=> [#<Object:0x7f361c5c33d0>, #<Object:0x7f361c5a9890>]
irb(main):008:0> b=Object.new
=> #<Object:0x7f361c5941c0>

In this example, nothing gets garbage collected. I allocated three
Objects, and one Array. At the end of execution, the Array is pointed to
by a, and two of the Objects are pointed to by the Array. The third
Object is pointed to by b.

--
--
@_bruno_antunes
sardaukar.siet@gmail.com
http://iruel.net

Thanks a lot James for your clarification.

Actually, I;m familiar with scoping as I dealt with it in Java, and new
to Ruby, and my point was the garbage collection here.

So, can I say that "word" in puts "#{word}" after the do-block is
garbage collected since I know more have access to it?

···

--
Posted via http://www.ruby-forum.com/.

Thanks James.

It didn't work me when I wrote your script as follows:

a = [1, 2, 3]
a.find {|x| x > 3}
puts a
puts x

Why doesn't that give the same output as in the format written by you,
while I can see that the logic here is correct?

···

--
Posted via http://www.ruby-forum.com/.

Java's garbage collected, too. So it's just the same as in there. I imagine you've missed a central feature of Java somewhere :wink:

The simple difference between garbage collection and non-garbage-collection is what happens when something falls out of scope. In C++, C, other languages that have manual memory management only, you have to free up the RAM assigned to the variable. In Java, Ruby, Python, Perl, those languages, the variable falls out of scope and the interpreter or compiler automatically frees the memory up for you.

Go read up on garbage collection. Garbage collection (computer science) - Wikipedia isn't atrocious, but maybe pick up a cheap computer science textbook or something.

The relationship you're proposing is essentially correct, though. You no longer have access to "word", so it's garbage collected. The memory associated with it is freed up and your computer goes on living its quiet, binary life, sadly contemplating a time when its memory was full of ones and zeroes in orderly, useful fashion.

Best

James

···

On Jul 13, 2010, at 10:06 AM 7/13/10, Abder-Rahman Ali wrote:

Thanks a lot James for your clarification.

Actually, I;m familiar with scoping as I dealt with it in Java, and new
to Ruby, and my point was the garbage collection here.

So, can I say that "word" in puts "#{word}" after the do-block is
garbage collected since I know more have access to it?
--
Posted via http://www.ruby-forum.com/\.

Thanks a lot James for your advice. Yes, think have to read more deeply
about garbage collection.

···

--
Posted via http://www.ruby-forum.com/.

Thanks a lot James for your advice. Yes, think have to read more deeply
about garbage collection.

This looks like the perfect opportunity to send this conversation way
into technical land.

Consider the following presentation and then GC system:
Joe Damato does a great job explaining GC under Ruby.
http://timetobleed.com/garbage-collection-and-the-ruby-heap-from-railsconf/

I have also been reading up on a GC system called Schism- a real-time,
concurrent non-moving, non-copying GC for java. I contacted the
university listed as being a collaborate on this Schism. Sadly it is
proprietary.
However, if I could ever free up some time, I was going to check how
patent encumbered it is. If the road is clear, then this would be a
great thing to have in ruby.
www.filpizlo.com/slides/pizlo-pldi2010-schism-slides.pdf

For those who don't know, GC is often blamed- generally rightly so-
for the biggest reason why ruby is slow.

I have no affiliate with either of these links.

Andrew McElroy

···

On Tue, Jul 13, 2010 at 11:24 AM, Abder-Rahman Ali <abder.rahman.ali@gmail.com> wrote:

--
Posted via http://www.ruby-forum.com/\.

Thanks Andrew. Helpful...

···

--
Posted via http://www.ruby-forum.com/.

Joe Damato did a good talk on this subject recently:

  http://blog.envylabs.com/2010/07/garbage-collection-the-ruby-heap/

···

On Tue, Jul 13, 2010 at 7:42 PM, Abder-Rahman Ali < abder.rahman.ali@gmail.com> wrote:

Thanks Andrew. Helpful...
--
Posted via http://www.ruby-forum.com/\.