How to understand why object is not collected?

Hi all.

Here's a problem.

I have some object of MyClass with complex "freeing" logic, and I want to
test this logic.
I do:

···

---------
span = .... #somehow created object

ObjectSpace.define_finalizer(span, proc{p "gc ok"}) #define test finalizer

span.detach #remove object from all of my internal caches, no references
to object should exist

span = nil #remove the last reference to object

GC.start #<===HERE the object must be collected and finalized

p "end of code"
---------

I expect:
---
"gc ok"
"end of code"
---

I receive:
---
"end of code"
"gc ok"
---

OK, I suppose there are some references to the object still exists. I want
to know, at least, what number of references still exists (in ideal, I'd
want to know, where they are).
How I can? (except of harcode hacking GC's C code)

Ruby 1.9 (downloaded a week ago), Windows.

Thanks.

V.

Victor "Zverok" Shepelev wrote:

Hi all.

Here's a problem.

I have some object of MyClass with complex "freeing" logic, and I want to
test this logic.
I do:

---------
span = .... #somehow created object

ObjectSpace.define_finalizer(span, proc{p "gc ok"}) #define test finalizer

span.detach #remove object from all of my internal caches, no references
to object should exist

span = nil #remove the last reference to object

GC.start #<===HERE the object must be collected and finalized

This is probably a situation where GC is being conservative. A simple example:

class Foo; end

foo = Foo.new
foo = nil

GC.start

p ObjectSpace.each_object(Foo) {} # ==> 1

Probably this means that the Foo instance pointer is still visible somewhere in the local frame.

But that doesn't mean that there is a leak:

class Foo; end

10.times do
   Foo.new
end

GC.start

p ObjectSpace.each_object(Foo) {} # ==> 1

In my experience, it's hard to write precise unit tests for GC behavior, and you end up with some fuzziness. The important property of GC is really the asymptotic behavior.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Hard to say what is going wrong but the solution is simple. Whenever
you have a resource that must be released, do it explicitly. The way
this is usually implemented is either:

  f = File.open 'foo'
  puts f.read
  f.close

Or, more conveniently

  File.open('foo') {|f| puts f.read}

The block-form uses ensure to make sure the file handle gets closed.

···

On 2006.10.29 03:26, Victor Zverok Shepelev wrote:

Hi all.

Here's a problem.

I have some object of MyClass with complex "freeing" logic, and I want to
test this logic.
<snip />

This is probably a situation where GC is being conservative. A simple
example:

class Foo; end

foo = Foo.new
foo = nil

GC.start

p ObjectSpace.each_object(Foo) {} # ==> 1

OK, I've got it.

In my experience, it's hard to write precise unit tests for GC behavior,
and you end up with some fuzziness. The important property of GC is
really the asymptotic behavior.

Just for now, I need no precise unit test. I just want to know, would the
objects of MyClass collected in principle. Can I achieve the goal somehow?

V.

···

From: Joel VanderWerf [mailto:vjoel@path.berkeley.edu]
Sent: Saturday, October 28, 2006 10:52 PM

Hi all.

Here's a problem.

I have some object of MyClass with complex "freeing" logic, and I want to
test this logic.
<snip />

Hard to say what is going wrong but the solution is simple. Whenever
you have a resource that must be released, do it explicitly. The way
this is usually implemented is either:

f = File.open 'foo'
puts f.read
f.close

Or, more conveniently

File.open('foo') {|f| puts f.read}

The block-form uses ensure to make sure the file handle gets closed.

I know this (I was C++ guy foe many years, so RAII is my breath), but can't
use.
My objects are HTML DOM elements and I want to be sure they are GC'd when
detached from DOM and have no other references.

V.

···

From: Eero Saynatkari [mailto:ruby-ml@kittensoft.org]
Sent: Saturday, October 28, 2006 11:20 PM

On 2006.10.29 03:26, Victor Zverok Shepelev wrote:

Victor "Zverok" Shepelev wrote:

From: Joel VanderWerf [mailto:vjoel@path.berkeley.edu]
Sent: Saturday, October 28, 2006 10:52 PM

This is probably a situation where GC is being conservative. A simple
example:

class Foo; end

foo = Foo.new
foo = nil

GC.start

p ObjectSpace.each_object(Foo) {} # ==> 1

OK, I've got it.

In my experience, it's hard to write precise unit tests for GC behavior,
and you end up with some fuzziness. The important property of GC is
really the asymptotic behavior.

Just for now, I need no precise unit test. I just want to know, would the
objects of MyClass collected in principle. Can I achieve the goal somehow?

What about creating a lot of them in a loop, without keeping references? Then I would expect GC to leave at most one instance.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Victor "Zverok" Shepelev wrote:

From: Joel VanderWerf [mailto:vjoel@path.berkeley.edu]
Sent: Saturday, October 28, 2006 10:52 PM

This is probably a situation where GC is being conservative. A simple
example:

class Foo; end

foo = Foo.new
foo = nil

GC.start

p ObjectSpace.each_object(Foo) {} # ==> 1

OK, I've got it.

In my experience, it's hard to write precise unit tests for GC behavior,
and you end up with some fuzziness. The important property of GC is
really the asymptotic behavior.

Just for now, I need no precise unit test. I just want to know, would the
objects of MyClass collected in principle. Can I achieve the goal

somehow?

What about creating a lot of them in a loop, without keeping references?
Then I would expect GC to leave at most one instance.

They can't be created by .new, they created in correspondence to some HTML
DOM by C extension.
Problem already solved by the trick:

···

From: Joel VanderWerf [mailto:vjoel@path.berkeley.edu]
Sent: Saturday, October 28, 2006 11:26 PM

--
def test
  span = ....
  ObjectSpace.define_finalizer(span, proc{p "gc ok"})
  span.detach
  span = nil
end

test

GC.start

p "end of code"
--

Output corresponds to my expectations (gc ok => end of code)

Thanks for your help!

V.