How to count existing instances of a class in ruby?

前端 未结 2 585
孤城傲影
孤城傲影 2020-12-18 10:17

Here\'s an idea from this question: Upon object creation, increment a class variable. When object gets collected, decrement it. As you can observe, finalizer is called, and

2条回答
  •  一个人的身影
    2020-12-18 10:41

    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
     => # 
    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 #
    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
     => # 
    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.

提交回复
热议问题