[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Collecting garbage

Eustaquio Rangel de Oliveira Jr.

7/6/2005 9:14:00 PM

Hi.

I have a doubt about garbage collection:

----------------------------------------------------------------------------------------
class CustomObject
attr_accessor :val, :next
def initialize(v,n=nil)
@val = v
@next = n
end
def to_s
"Object #{@val} (#{self.object_id}) points to #{@next.nil? ? 'nothing' :
@next.val} (#{@next.nil? ? '':@next.object_id})"
end
end

def list
print "Listing all CustomObject's with ObjectSpace\n"
print "#{ObjectSpace.each_object(CustomObject) {|v| puts v}} objects
found\n\n"
end

c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
c4 = CustomObject.new("4",CustomObject.new("5"))
c6 = CustomObject.new("6")
c1.next.next.next = c1 # comment this and check again
list

c1 = nil
c4.next = nil

GC.start # here I want c1 disappears
sleep(1)
list
----------------------------------------------------------------------------------------

running this program I get

----------------------------------------------------------------------------------------
Listing all CustomObject's with ObjectSpace
Object 6 (-604874926) points to nothing ()
Object 4 (-604874906) points to 5 (-604874896)
Object 5 (-604874896) points to nothing ()
Object 1 (-604874866) points to 2 (-604874856)
Object 2 (-604874856) points to 3 (-604874846)
Object 3 (-604874846) points to 1 (-604874866)
6 objects found

Listing all CustomObject's with ObjectSpace
Object 6 (-604874926) points to nothing ()
Object 4 (-604874906) points to nothing ()
Object 1 (-604874866) points to 2 (-604874856)
Object 2 (-604874856) points to 3 (-604874846)
Object 3 (-604874846) points to 1 (-604874866)
5 objects found
----------------------------------------------------------------------------------------

There's a circular reference there: c1 points to 2 (created internally on
1), 2 points to 3 (created internally on 2), and 3 points to c1, which is a
reference at root (?) level there and again points to an internal 2, that
points to 3, that points to c1 ...

My question is, when assigning nil to c1, it should not invalidate all the
inner objects and becomes available for garbage collection?
On the example above, I assigned nil to c1 and c4.next (5), and after the
GC.start I don't have 5, but still have c1 (same id), 2 and 3. On that
case, that memory will never be sweeped (free)? Because seems that I'll
always have a Object with id -604874856 and will not have a way to refer to
it later, for use or free the allocated memory for it.

Thanks.

----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://b...
Usuário GNU/Linux no. 224050



8 Answers

Yohanes Santoso

7/6/2005 9:58:00 PM

0

"Eustaquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> writes:

> My question is, when assigning nil to c1, it should not invalidate all
> the inner objects and becomes available for garbage collection?
> On the example above, I assigned nil to c1 and c4.next (5), and after
> the GC.start I don't have 5, but still have c1 (same id), 2 and 3. On
> that case, that memory will never be sweeped (free)? Because seems
> that I'll always have a Object with id -604874856 and will not have a
> way to refer to it later, for use or free the allocated memory for it.

Ruby's GC is lazy and conservative. Lazy meaning, it does not
exhaustively try to do path-finding on each object because for some
objects, path-finding is an expensive process. Conservative meaning,
if it is not doing a path-finding on an object, that object is not
freed.

Hate it or love it. It has both advantages and disadvantages. You have
just shown a disadvantage. But it can be mitigated by exiting the
scope which should make path-finding to those objects cheaper.



class CustomObject
attr_accessor :val, :next
def initialize(v,n=nil)
@val = v
@next = n
end
def to_s
"Object #{@val} (#{self.object_id}) points to #{@next.nil? ? 'nothing' : @next.val} (#{@next.nil? ? '':@next.object_id})"
end
end

def list
print "Listing all CustomObject's with ObjectSpace\n"
print "#{ObjectSpace.each_object(CustomObject) {|v| puts v}} objects found\n\n"
end

begin # start a new scope so we can exit it later
c1 = CustomObject.new(1,CustomObject.new(2,CustomObject.new(3)))
c4 = CustomObject.new(4,CustomObject.new(5))
c6 = CustomObject.new(6)
c1.next.next.next = c1 # comment this and check again
puts "### Initial"
list

c1 = nil
c4.next = nil

GC.start

puts "### After gc, but still within declaring scope"
list
end

puts "### Exitted the scope"
list

GC.start # here I want c1 disappears

puts "### After gc, outside of declaring scope"
list




Output:

### Initial
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to 5 (-604561922)
Object 5 (-604561922) points to nothing ()
Object 1 (-604561912) points to 2 (-604561902)
Object 2 (-604561902) points to 3 (-604561892)
Object 3 (-604561892) points to 1 (-604561912)
6 objects found

### After gc, but still within declaring scope
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to nothing ()
Object 1 (-604561912) points to 2 (-604561902)
Object 2 (-604561902) points to 3 (-604561892)
Object 3 (-604561892) points to 1 (-604561912)
5 objects found

### Exitted the scope
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to nothing ()
Object 1 (-604561912) points to 2 (-604561902)
Object 2 (-604561902) points to 3 (-604561892)
Object 3 (-604561892) points to 1 (-604561912)
5 objects found

### After gc, outside of declaring scope
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to nothing ()
2 objects found


Yohanes Santoso

7/6/2005 10:03:00 PM

0

Yohanes Santoso <ysantoso-rubytalk@dessyku.is-a-geek.org> writes:

> exiting the scope which should make path-finding to those objects
> cheaper.

correction: declaring scope, not variable scope.

YS.



Eustaquio Rangel de Oliveira Jr.

7/7/2005 11:02:00 AM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

Thanks for the answer. :-)

| Ruby's GC is lazy and conservative. Lazy meaning, it does not
| exhaustively try to do path-finding on each object because for some
| objects, path-finding is an expensive process. Conservative meaning,
| if it is not doing a path-finding on an object, that object is not
| freed.
|
| Hate it or love it. It has both advantages and disadvantages. You have
| just shown a disadvantage. But it can be mitigated by exiting the
| scope which should make path-finding to those objects cheaper.

I'll search about lazy and conversative gc's. :-)
Just another question: if I use a method there, and not a begin/end block,
like this

- --------------------------------------------------------------------------
def test
c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
c4 = CustomObject.new("4",CustomObject.new("5"))
c6 = CustomObject.new("6")
c1.next.next.next = c1 # comment this and check again
list
end

test
GC.start
sleep(1)
list
- --------------------------------------------------------------------------

After run this, only c6 remains. It's about scope also?

Thanks!

- ----------------------------
Eust?quio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://b...
Usu?rio GNU/Linux no. 224050
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.7 (GNU/Linux)

iD8DBQFCzQuLb6UiZnhJiLsRAq8mAKCZdk3XkCidxwRLhxKG7unSrBIdEQCeNkMh
Im7s5zjG8umPPDkrXwwgCk0=
=2bZr
-----END PGP SIGNATURE-----


Yohanes Santoso

7/7/2005 8:47:00 PM

0

"Eustaquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> writes:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi!
>
> Thanks for the answer. :-)
>
> | Ruby's GC is lazy and conservative. Lazy meaning, it does not
> | exhaustively try to do path-finding on each object because for some
> | objects, path-finding is an expensive process. Conservative meaning,
> | if it is not doing a path-finding on an object, that object is not
> | freed.
> |
> | Hate it or love it. It has both advantages and disadvantages. You have
> | just shown a disadvantage. But it can be mitigated by exiting the
> | scope which should make path-finding to those objects cheaper.
>
> I'll search about lazy and conversative gc's. :-)
> Just another question: if I use a method there, and not a begin/end block,
> like this
>
> - --------------------------------------------------------------------------
> def test
> c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
> c4 = CustomObject.new("4",CustomObject.new("5"))
> c6 = CustomObject.new("6")
> c1.next.next.next = c1 # comment this and check again
> list
> end
>
> test
> GC.start
> sleep(1)
> list
> - --------------------------------------------------------------------------
>
> After run this, only c6 remains. It's about scope also?
>

Funny, I couldn't reproduce what you are seeing. I cut and paste the
code you have and run it:

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
/tmp $ ruby1.8 ./gc.rb
Listing all CustomObject's with ObjectSpace
Object 6 (-604561642) points to nothing ()
Object 4 (-604561622) points to 5 (-604561612)
Object 5 (-604561612) points to nothing ()
Object 1 (-604561582) points to 2 (-604561572)
Object 2 (-604561572) points to 3 (-604561562)
Object 3 (-604561562) points to 1 (-604561582)
6 objects found

Listing all CustomObject's with ObjectSpace
0 objects found
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Nothing remains.

Probably you are seeing c6 remaining because you were playing with
your code like so:

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
def test
c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
c4 = CustomObject.new("4",CustomObject.new("5"))
c6 = CustomObject.new("6")
end

test
GC.start
sleep(1)
list
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Notice that c6 is returned from test, so the object refered to by c6
is now accessible from where you invoke GC.start and that is the
original problem.


YS.


Eustaquio Rangel de Oliveira Jr.

7/7/2005 9:06:00 PM

0

Hi!

> Probably you are seeing c6 remaining because you were playing with
> your code like so:

Not really, let me paste the full code here:
-------------------------------------------------------------------------------
class CustomObject
attr_accessor :val, :next
def initialize(v,n=nil)
@val = v
@next = n
end
def to_s
"Object #{@val} (#{self.object_id}) points to #{@next.nil? ? 'nothing' :
@next.val} (#{@next.nil? ? '':@next.object_id})"
end
end

def list
print "Listing all the CustomObject's with ObjectSpace\n"
print "#{ObjectSpace.each_object(CustomObject) {|v| puts v}} objects
found\n\n"
end

def test
c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
c4 = CustomObject.new("4",CustomObject.new("5"))
c6 = CustomObject.new("6")
c1.next.next.next = c1
list

c1 = nil
c4.next = nil
end

test
GC.start
sleep(1)
list
-------------------------------------------------------------------------------
running
-------------------------------------------------------------------------------
Listing all the CustomObject's with ObjectSpace
Object 6 (-604875086) points to nothing ()
Object 4 (-604875066) points to 5 (-604875056)
Object 5 (-604875056) points to nothing ()
Object 1 (-604875026) points to 2 (-604875016)
Object 2 (-604875016) points to 3 (-604875006)
Object 3 (-604875006) points to 1 (-604875026)
6 objects found

Listing all the CustomObject's with ObjectSpace
Object 6 (-604875086) points to nothing ()
1 objects found
-------------------------------------------------------------------------------

> Funny, I couldn't reproduce what you are seeing.
> Nothing remains.

Maybe a situation like this:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...

But the main point of this question you solved: the begin ... end works
perfectly.

Thanks!

----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://b...
Usuário GNU/Linux no. 224050


Yohanes Santoso

7/7/2005 9:14:00 PM

0

"Eustaquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> writes:

> Not really, let me paste the full code here:

> Listing all the CustomObject's with ObjectSpace
> Object 6 (-604875086) points to nothing ()
> 1 objects found

Still same thing, I got 0 objects found at the end.

But I'm glad you have satisfied your curiosity.

YS.


Jay Cotton

7/13/2005 1:43:00 PM

0

I've been following this thread as well as why's post (and the
comments) at:

http://redhanded.hobix.com/inspect/stuffingYourHandDownTheDis...

and I'm left confused about 2 things:

1) What sort of scope does begin..end introduce? In the comments to
his post, why writes "Variables declared inside a begin..end or
inside a block are block local, they perish with the close of the
block." But my own experience seems to contradict why's statement.
This program does not throw an error:

#!/usr/local/bin/ruby
begin
x = 1
end
p x

2) Why are people getting different results when they run the CustObj
garbage collection code? When I run it, Object 1 never gets collected
by GC, even after exiting the begin..end scope.

Can anybody help me understand?

Jay



Eric Hodel

7/13/2005 9:30:00 PM

0


On 13 Jul 2005, at 06:43, Jay Cotton wrote:

> I've been following this thread as well as why's post (and the
> comments) at:
>
> http://redhanded.hobix.co...
> stuffingYourHandDownTheDisposal.html
>
> and I'm left confused about 2 things:
>
> 1) What sort of scope does begin..end introduce? In the comments to
> his post, why writes "Variables declared inside a begin..end or
> inside a block are block local, they perish with the close of the
> block." But my own experience seems to contradict why's statement.
> This program does not throw an error:
>
> #!/usr/local/bin/ruby
> begin
> x = 1
> end
> p x

begin does not create a new scope. why made a mistake here.

> 2) Why are people getting different results when they run the
> CustObj garbage collection code? When I run it, Object 1 never gets
> collected by GC, even after exiting the begin..end scope.
>
> Can anybody help me understand?

The GC is very finicky, so you may or may not get the same behavior
as other people do. That's part of the nature of Ruby's conservative
GC.

--
Eric Hodel - drbrain@segment7.net - http://se...
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04