Collecting garbage

Discussion in 'Ruby' started by Eustaquio Rangel de Oliveira Jr., Jul 6, 2005.

  1. Hi.

    I have a doubt about garbage collection:

    -------------------------------------------------------------------------=
    ---------------
    class CustomObject
    attr_accessor :val, :next
    def initialize(v,n=3Dnil)
    @val =3D v
    @next =3D n
    end
    def to_s
    "Object #{@val} (#{self.object_id}) points to #{@next.nil? ? 'nothing' =
    :=20
    @next.val} (#{@next.nil? ? '':mad:next.object_id})"
    end
    end

    def list
    print "Listing all CustomObject's with ObjectSpace\n"
    print "#{ObjectSpace.each_object(CustomObject) {|v| puts v}} objects=20
    found\n\n"
    end

    c1 =3D CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
    c4 =3D CustomObject.new("4",CustomObject.new("5"))
    c6 =3D CustomObject.new("6")
    c1.next.next.next =3D c1 # comment this and check again
    list

    c1 =3D nil
    c4.next =3D nil

    GC.start # here I want c1 disappears
    sleep(1)
    list
    -------------------------------------------------------------------------=
    ---------------

    running this program I get

    -------------------------------------------------------------------------=
    ---------------
    Listing all CustomObject's with ObjectSpace
    Object 6 (-604874926) points to nothing ()
    Object 4 (-604874906) points to 5 (-604874896)
    Object 5 (-604874896) points to nothing ()
    Object 1 (-604874866) points to 2 (-604874856)
    Object 2 (-604874856) points to 3 (-604874846)
    Object 3 (-604874846) points to 1 (-604874866)
    6 objects found

    Listing all CustomObject's with ObjectSpace
    Object 6 (-604874926) points to nothing ()
    Object 4 (-604874906) points to nothing ()
    Object 1 (-604874866) points to 2 (-604874856)
    Object 2 (-604874856) points to 3 (-604874846)
    Object 3 (-604874846) points to 1 (-604874866)
    5 objects found
    -------------------------------------------------------------------------=
    ---------------

    There's a circular reference there: c1 points to 2 (created internally on=
    =20
    1), 2 points to 3 (created internally on 2), and 3 points to c1, which is=
    a=20
    reference at root (?) level there and again points to an internal 2, that=
    =20
    points to 3, that points to c1 ...

    My question is, when assigning nil to c1, it should not invalidate all th=
    e=20
    inner objects and becomes available for garbage collection?
    On the example above, I assigned nil to c1 and c4.next (5), and after the=
    =20
    GC.start I don't have 5, but still have c1 (same id), 2 and 3. On that=20
    case, that memory will never be sweeped (free)? Because seems that I'll=20
    always have a Object with id -604874856 and will not have a way to refer =
    to=20
    it later, for use or free the allocated memory for it.

    Thanks.

    ----------------------------
    Eust=E1quio "TaQ" Rangel

    http://beam.to/taq
    Usu=E1rio GNU/Linux no. 224050
    Eustaquio Rangel de Oliveira Jr., Jul 6, 2005
    #1
    1. Advertising

  2. "Eustaquio Rangel de Oliveira Jr." <> writes:

    > My question is, when assigning nil to c1, it should not invalidate all
    > the inner objects and becomes available for garbage collection?
    > On the example above, I assigned nil to c1 and c4.next (5), and after
    > the GC.start I don't have 5, but still have c1 (same id), 2 and 3. On
    > that case, that memory will never be sweeped (free)? Because seems
    > that I'll always have a Object with id -604874856 and will not have a
    > way to refer to it later, for use or free the allocated memory for it.


    Ruby's GC is lazy and conservative. Lazy meaning, it does not
    exhaustively try to do path-finding on each object because for some
    objects, path-finding is an expensive process. Conservative meaning,
    if it is not doing a path-finding on an object, that object is not
    freed.

    Hate it or love it. It has both advantages and disadvantages. You have
    just shown a disadvantage. But it can be mitigated by exiting the
    scope which should make path-finding to those objects cheaper.



    class CustomObject
    attr_accessor :val, :next
    def initialize(v,n=nil)
    @val = v
    @next = n
    end
    def to_s
    "Object #{@val} (#{self.object_id}) points to #{@next.nil? ? 'nothing' : @next.val} (#{@next.nil? ? '':mad:next.object_id})"
    end
    end

    def list
    print "Listing all CustomObject's with ObjectSpace\n"
    print "#{ObjectSpace.each_object(CustomObject) {|v| puts v}} objects found\n\n"
    end

    begin # start a new scope so we can exit it later
    c1 = CustomObject.new(1,CustomObject.new(2,CustomObject.new(3)))
    c4 = CustomObject.new(4,CustomObject.new(5))
    c6 = CustomObject.new(6)
    c1.next.next.next = c1 # comment this and check again
    puts "### Initial"
    list

    c1 = nil
    c4.next = nil

    GC.start

    puts "### After gc, but still within declaring scope"
    list
    end

    puts "### Exitted the scope"
    list

    GC.start # here I want c1 disappears

    puts "### After gc, outside of declaring scope"
    list




    Output:

    ### Initial
    Listing all CustomObject's with ObjectSpace
    Object 6 (-604561942) points to nothing ()
    Object 4 (-604561932) points to 5 (-604561922)
    Object 5 (-604561922) points to nothing ()
    Object 1 (-604561912) points to 2 (-604561902)
    Object 2 (-604561902) points to 3 (-604561892)
    Object 3 (-604561892) points to 1 (-604561912)
    6 objects found

    ### After gc, but still within declaring scope
    Listing all CustomObject's with ObjectSpace
    Object 6 (-604561942) points to nothing ()
    Object 4 (-604561932) points to nothing ()
    Object 1 (-604561912) points to 2 (-604561902)
    Object 2 (-604561902) points to 3 (-604561892)
    Object 3 (-604561892) points to 1 (-604561912)
    5 objects found

    ### Exitted the scope
    Listing all CustomObject's with ObjectSpace
    Object 6 (-604561942) points to nothing ()
    Object 4 (-604561932) points to nothing ()
    Object 1 (-604561912) points to 2 (-604561902)
    Object 2 (-604561902) points to 3 (-604561892)
    Object 3 (-604561892) points to 1 (-604561912)
    5 objects found

    ### After gc, outside of declaring scope
    Listing all CustomObject's with ObjectSpace
    Object 6 (-604561942) points to nothing ()
    Object 4 (-604561932) points to nothing ()
    2 objects found
    Yohanes Santoso, Jul 6, 2005
    #2
    1. Advertising

  3. Yohanes Santoso <-a-geek.org> writes:

    > exiting the scope which should make path-finding to those objects
    > cheaper.


    correction: declaring scope, not variable scope.

    YS.
    Yohanes Santoso, Jul 6, 2005
    #3
  4. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Hi!

    Thanks for the answer. :)

    | Ruby's GC is lazy and conservative. Lazy meaning, it does not
    | exhaustively try to do path-finding on each object because for some
    | objects, path-finding is an expensive process. Conservative meaning,
    | if it is not doing a path-finding on an object, that object is not
    | freed.
    |
    | Hate it or love it. It has both advantages and disadvantages. You have
    | just shown a disadvantage. But it can be mitigated by exiting the
    | scope which should make path-finding to those objects cheaper.

    I'll search about lazy and conversative gc's. :)
    Just another question: if I use a method there, and not a begin/end block,
    like this

    - --------------------------------------------------------------------------
    def test
    c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
    c4 = CustomObject.new("4",CustomObject.new("5"))
    c6 = CustomObject.new("6")
    c1.next.next.next = c1 # comment this and check again
    list
    end

    test
    GC.start
    sleep(1)
    list
    - --------------------------------------------------------------------------

    After run this, only c6 remains. It's about scope also?

    Thanks!

    - ----------------------------
    Eust?quio "TaQ" Rangel

    http://beam.to/taq
    Usu?rio GNU/Linux no. 224050
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.7 (GNU/Linux)

    iD8DBQFCzQuLb6UiZnhJiLsRAq8mAKCZdk3XkCidxwRLhxKG7unSrBIdEQCeNkMh
    Im7s5zjG8umPPDkrXwwgCk0=
    =2bZr
    -----END PGP SIGNATURE-----
    Eustaquio Rangel de Oliveira Jr., Jul 7, 2005
    #4
  5. "Eustaquio Rangel de Oliveira Jr." <> writes:

    > -----BEGIN PGP SIGNED MESSAGE-----
    > Hash: SHA1
    >
    > Hi!
    >
    > Thanks for the answer. :)
    >
    > | Ruby's GC is lazy and conservative. Lazy meaning, it does not
    > | exhaustively try to do path-finding on each object because for some
    > | objects, path-finding is an expensive process. Conservative meaning,
    > | if it is not doing a path-finding on an object, that object is not
    > | freed.
    > |
    > | Hate it or love it. It has both advantages and disadvantages. You have
    > | just shown a disadvantage. But it can be mitigated by exiting the
    > | scope which should make path-finding to those objects cheaper.
    >
    > I'll search about lazy and conversative gc's. :)
    > Just another question: if I use a method there, and not a begin/end block,
    > like this
    >
    > - --------------------------------------------------------------------------
    > def test
    > c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
    > c4 = CustomObject.new("4",CustomObject.new("5"))
    > c6 = CustomObject.new("6")
    > c1.next.next.next = c1 # comment this and check again
    > list
    > end
    >
    > test
    > GC.start
    > sleep(1)
    > list
    > - --------------------------------------------------------------------------
    >
    > After run this, only c6 remains. It's about scope also?
    >


    Funny, I couldn't reproduce what you are seeing. I cut and paste the
    code you have and run it:

    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    /tmp $ ruby1.8 ./gc.rb
    Listing all CustomObject's with ObjectSpace
    Object 6 (-604561642) points to nothing ()
    Object 4 (-604561622) points to 5 (-604561612)
    Object 5 (-604561612) points to nothing ()
    Object 1 (-604561582) points to 2 (-604561572)
    Object 2 (-604561572) points to 3 (-604561562)
    Object 3 (-604561562) points to 1 (-604561582)
    6 objects found

    Listing all CustomObject's with ObjectSpace
    0 objects found
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Nothing remains.

    Probably you are seeing c6 remaining because you were playing with
    your code like so:

    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    def test
    c1 = CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
    c4 = CustomObject.new("4",CustomObject.new("5"))
    c6 = CustomObject.new("6")
    end

    test
    GC.start
    sleep(1)
    list
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Notice that c6 is returned from test, so the object refered to by c6
    is now accessible from where you invoke GC.start and that is the
    original problem.


    YS.
    Yohanes Santoso, Jul 7, 2005
    #5
  6. Hi!

    > Probably you are seeing c6 remaining because you were playing with
    > your code like so:=20


    Not really, let me paste the full code here:
    -------------------------------------------------------------------------=
    ------
    class CustomObject
    attr_accessor :val, :next
    def initialize(v,n=3Dnil)
    @val =3D v
    @next =3D n
    end
    def to_s
    "Object #{@val} (#{self.object_id}) points to #{@next.nil? ? 'nothing' =
    :=20
    @next.val} (#{@next.nil? ? '':mad:next.object_id})"
    end
    end

    def list
    print "Listing all the CustomObject's with ObjectSpace\n"
    print "#{ObjectSpace.each_object(CustomObject) {|v| puts v}} objects=20
    found\n\n"
    end

    def test
    c1 =3D CustomObject.new("1",CustomObject.new("2",CustomObject.new("3")))
    c4 =3D CustomObject.new("4",CustomObject.new("5"))
    c6 =3D CustomObject.new("6")
    c1.next.next.next =3D c1=09
    list

    c1 =3D nil
    c4.next =3D nil
    end

    test
    GC.start =09
    sleep(1)
    list
    -------------------------------------------------------------------------=
    ------
    running
    -------------------------------------------------------------------------=
    ------
    Listing all the CustomObject's with ObjectSpace
    Object 6 (-604875086) points to nothing ()
    Object 4 (-604875066) points to 5 (-604875056)
    Object 5 (-604875056) points to nothing ()
    Object 1 (-604875026) points to 2 (-604875016)
    Object 2 (-604875016) points to 3 (-604875006)
    Object 3 (-604875006) points to 1 (-604875026)
    6 objects found

    Listing all the CustomObject's with ObjectSpace
    Object 6 (-604875086) points to nothing ()
    1 objects found
    -------------------------------------------------------------------------=
    ------

    > Funny, I couldn't reproduce what you are seeing.
    > Nothing remains.


    Maybe a situation like this:
    http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/142834

    But the main point of this question you solved: the begin ... end works=20
    perfectly.

    Thanks!

    ----------------------------
    Eust=E1quio "TaQ" Rangel

    http://beam.to/taq
    Usu=E1rio GNU/Linux no. 224050
    Eustaquio Rangel de Oliveira Jr., Jul 7, 2005
    #6
  7. "Eustaquio Rangel de Oliveira Jr." <> writes:

    > Not really, let me paste the full code here:


    > Listing all the CustomObject's with ObjectSpace
    > Object 6 (-604875086) points to nothing ()
    > 1 objects found


    Still same thing, I got 0 objects found at the end.

    But I'm glad you have satisfied your curiosity.

    YS.
    Yohanes Santoso, Jul 7, 2005
    #7
  8. Eustaquio Rangel de Oliveira Jr.

    Jay Cotton Guest

    I've been following this thread as well as why's post (and the
    comments) at:

    http://redhanded.hobix.com/inspect/stuffingYourHandDownTheDisposal.html

    and I'm left confused about 2 things:

    1) What sort of scope does begin..end introduce? In the comments to
    his post, why writes "Variables declared inside a begin..end or
    inside a block are block local, they perish with the close of the
    block." But my own experience seems to contradict why's statement.
    This program does not throw an error:

    #!/usr/local/bin/ruby
    begin
    x = 1
    end
    p x

    2) Why are people getting different results when they run the CustObj
    garbage collection code? When I run it, Object 1 never gets collected
    by GC, even after exiting the begin..end scope.

    Can anybody help me understand?

    Jay
    Jay Cotton, Jul 13, 2005
    #8
  9. Eustaquio Rangel de Oliveira Jr.

    Eric Hodel Guest

    On 13 Jul 2005, at 06:43, Jay Cotton wrote:

    > I've been following this thread as well as why's post (and the
    > comments) at:
    >
    > http://redhanded.hobix.com/inspect/
    > stuffingYourHandDownTheDisposal.html
    >
    > and I'm left confused about 2 things:
    >
    > 1) What sort of scope does begin..end introduce? In the comments to
    > his post, why writes "Variables declared inside a begin..end or
    > inside a block are block local, they perish with the close of the
    > block." But my own experience seems to contradict why's statement.
    > This program does not throw an error:
    >
    > #!/usr/local/bin/ruby
    > begin
    > x = 1
    > end
    > p x


    begin does not create a new scope. why made a mistake here.

    > 2) Why are people getting different results when they run the
    > CustObj garbage collection code? When I run it, Object 1 never gets
    > collected by GC, even after exiting the begin..end scope.
    >
    > Can anybody help me understand?


    The GC is very finicky, so you may or may not get the same behavior
    as other people do. That's part of the nature of Ruby's conservative
    GC.

    --
    Eric Hodel - - http://segment7.net
    FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
    Eric Hodel, Jul 13, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roger Irwin

    Garbage collecting on nulls.......

    Roger Irwin, Jul 23, 2003, in forum: Java
    Replies:
    4
    Views:
    455
    Dario
    Jul 24, 2003
  2. Scott W Gifford
    Replies:
    4
    Views:
    760
    Scott W Gifford
    Dec 16, 2005
  3. Replies:
    1
    Views:
    440
    mrstephengross
    Jul 25, 2005
  4. Robert Potthast

    Safe garbage collecting

    Robert Potthast, Sep 4, 2005, in forum: C++
    Replies:
    10
    Views:
    473
    Robert Potthast
    Sep 5, 2005
  5. Yuanxin Xi
    Replies:
    7
    Views:
    285
    Steve Holden
    Feb 26, 2009
Loading...

Share This Page