Search code examples
ruby-on-railsrubyheap-memoryobjectspace

ObjectSpace.each_object(Foo).count


I'am trying to figure out ObjectSpace.each_object
In console:

class Foo; end  
Foo.new  
ObjectSpace.each_object(Foo).count  
=> 1  
GC.start  
ObjectSpace.each_object(Foo).count  
=> 1 

I've seen examples and I know that the second count should be 0.
Any ideas what is going on here?
Thanks.


Solution

  • It depends on your console.

    IRB

    The last result is saved as _, even if it hasn't been explicitely assigned. Running GC.start won't remove the last object :

    irb(main):001:0> class Foo; end
    => nil
    irb(main):002:0>
    irb(main):003:0* Foo.new
    => #<Foo:0x007fca7a309f98>
    irb(main):004:0> p ObjectSpace.each_object(Foo).count; GC.start; p ObjectSpace.each_object(Foo).count
    1
    1
    => 1
    irb(main):005:0> p ObjectSpace.each_object(Foo).count; GC.start; p ObjectSpace.each_object(Foo).count
    1
    0
    => 0
    

    Pry

    You can access the last result and the second to last result with _ and __ :

    [1] pry(main)> 'a'
    => "a"
    [2] pry(main)> 'b'
    => "b"
    [3] pry(main)> p _, __
    "b"
    "a"
    => ["b", "a"]
    

    Pry saves all the 100 last results in _out_ Pry::HistoryArray:

    [1] pry(main)> class Foo; end
    => nil
    [2] pry(main)> Foo.new
    => #<Foo:0x007fd093102118>
    [3] pry(main)> ObjectSpace.each_object(Foo).count
    => 1
    [4] pry(main)> GC.start
    => nil
    [5] pry(main)> ObjectSpace.each_object(Foo).count
    => 1
    [6] pry(main)> _out_[2]
    => #<Foo:0x007fd093102118>
    

    You can use _out_.pop! to remove its last element :

    [1] pry(main)> class Foo; end
    => nil
    [2] pry(main)> Foo.new
    => #<Foo:0x007fa90b1ad360>
    [3] pry(main)> ObjectSpace.each_object(Foo).count
    => 1
    [4] pry(main)> GC.start
    => nil
    [5] pry(main)> ObjectSpace.each_object(Foo).count
    => 1
    [6] pry(main)> 5.times{_out_.pop!}
    => 5
    [7] pry(main)> GC.start
    => nil
    [8] pry(main)> ObjectSpace.each_object(Foo).count
    => 0
    

    Inside a script

    If you execute :

    class Foo; end
    
    Foo.new
    p ObjectSpace.each_object(Foo).count
    
    GC.start
    p ObjectSpace.each_object(Foo).count
    

    inside a script, you get :

    1
    0