Finalization is not happening when you think it should in the code you provided.
For example, if you change that one line to:
ObjectSpace.define_finalizer(self, proc do; puts "self is type #{self.class.name} and equals #{self.inspect}"; self.delete; end)
Then notice how it does nothing (even if I sit there and wait a while) until I kill irb:
... (entered class definition from above with that define_finalizer)
1.9.3-p392 :021 > Foo.no_foo # => 0
=> 0
1.9.3-p392 :022 > f = Foo.new
creating object
=> #<Foo:0x007fb5730f3e00>
1.9.3-p392 :023 > f = nil
=> nil
1.9.3-p392 :024 >
1.9.3-p392 :025 > GC.start
=> nil
1.9.3-p392 :026 > Foo.no_foo # => 1
=> 1
1.9.3-p392 :027 > ^D
self is type Foo and equals #<Foo:0x007fb5730f3e00>
deleting object
So the first assumption may be that GC was not invoked. But, lets look at it using GC::Profiler
:
1.9.3p392 :001 > GC::Profiler.enable
... (entered class definition from above)
1.9.3p392 :022 > puts GC::Profiler.result
GC 17 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
=> nil
1.9.3p392 :023 > Foo.no_foo # => 0
=> 0
1.9.3p392 :024 > f = Foo.new
creating object
=> #<Foo:0x007fe2fc806808>
1.9.3p392 :025 > puts GC::Profiler.result
GC 17 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
=> nil
1.9.3p392 :026 > f = nil
=> nil
1.9.3p392 :027 > puts GC::Profiler.result
GC 17 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
=> nil
1.9.3p392 :028 > GC.start
=> nil
1.9.3p392 :029 > puts GC::Profiler.result
GC 18 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
1 0.161 997280 2257680 56442 3.96199999999999352696
=> nil
1.9.3p392 :030 > Foo.no_foo # => 1
=> 1
1.9.3p392 :031 > ^D
deleting object
So, it looks like the GC is getting invoked when you ask it to, but it is not finalizing the Foo instance until irb exit.
deleting object
at all. Also,ObjectSpace.each_object(Foo).count
gives me1
. – Roeslerputs Foo.no_foo
, i seedeleting object
after the puts, probably at exit. So i guessGC.start
does not actually collect the instance and the count of1
is correct at that time. – Roeslerdefine_finalizer
is called right before deletion, and under the description of the methoddefine_finalizer
, it says it is called right after. How can this both be true? Does anyone have clear idea on this? – Sahib