如何计算ruby中类的现有实例?

以下是这个问题的一个想法:在创建对象时,增加一个类变量。 当对象被收集时,减少它。 如您@@no_foo ,调用终结器,并且@@no_foo减少。 但是当我稍后查询它时,减量就消失了。 似乎价值只会上升,永不下降(如果我创建两个对象,它将显示2)。 我错过了一些明显的东西吗

 class Foo @@no_foo = 0 def initialize puts 'creating object' @@no_foo += 1 ObjectSpace.define_finalizer(self, proc { self.delete }) end def delete puts 'deleting object' @@no_foo # => 1 @@no_foo -= 1 @@no_foo # => 0 end def self.no_foo @@no_foo # => 0, 1 end end Foo.no_foo # => 0 f = Foo.new f = nil GC.start Foo.no_foo # => 1 # >> creating object # >> deleting object 

它可以工作,但在最终确定中有循环引用。 终结器取决于应该收集的对象的绑定。 看到这个解决方案

 class Foo @@no_foo = 0 def initialize @@no_foo += 1 ObjectSpace.define_finalizer(self, Foo.method(:delete)) end def self.delete id # also this argument seems to be necessary @@no_foo -= 1 end def self.no_foo @@no_foo end end Foo.no_foo # => 0 1000.times{Foo.new} Foo.no_foo # => 1000 GC.start Foo.no_foo # => 0 

如果您认为应该在您提供的代码中进行,则不会进行终结。

例如,如果您将该行更改为:

 ObjectSpace.define_finalizer(self, proc do; puts "self is type #{self.class.name} and equals #{self.inspect}"; self.delete; end) 

然后注意它什么都不做(即使我坐在那里等待一段时间)直到我杀了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 

所以第一个假设可能是没有调用GC。 但是,让我们使用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 

因此,当你提出要求时,看起来GC会被调用,但是在irb退出之前它还没有完成Foo实例。