Forum: Ruby Garbage collection and Arrays

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A24e072d6092870feff0d5016ff2cdd0?d=identicon&s=25 Aaron Patterson (Guest)
on 2007-01-19 16:30
(Received via mailing list)
Hi, I seem to be running in to some garbage collection weirdness.
Hopefully someone will have some insight for me....  My sample script
seems to leak Strings when I use shift on an Array, but not pop:

array = []
10.times { array << "foo" }
10.times { array.pop }  # Change this to shift to see a leak

o_count = Hash.new(0)
GC.start
ObjectSpace.each_object { |o| o_count[o.class] += 1 }

o_count.sort_by { |k,v| -v}.each { |k,v| puts "#{k}: #{v}" }

Is this a bug?  Or is there something I'm missing?  Thanks!

--Aaron
1b5341b64f7ce0244366eae17f06c801?d=identicon&s=25 unknown (Guest)
on 2007-01-19 16:31
(Received via mailing list)
On Fri, 12 Jan 2007, Aaron Patterson wrote:

> ObjectSpace.each_object { |o| o_count[o.class] += 1 }
>
> o_count.sort_by { |k,v| -v}.each { |k,v| puts "#{k}: #{v}" }
>
> Is this a bug?  Or is there something I'm missing?  Thanks!

Check the archives of the list for extensive discussion.  The upshot is
that it's a problem with this shift() method.


Kirk Haines
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2007-01-19 16:31
(Received via mailing list)
On 1/12/07, Aaron Patterson <aaron_patterson@speakeasy.net> wrote:
> Hi, I seem to be running in to some garbage collection weirdness.
> Hopefully someone will have some insight for me....  My sample script
> seems to leak Strings when I use shift on an Array, but not pop:

http://recursive.ca/hutch/index.php?p=361
A24e072d6092870feff0d5016ff2cdd0?d=identicon&s=25 Aaron Patterson (Guest)
on 2007-09-25 22:32
(Received via mailing list)
On Fri, Jan 12, 2007 at 04:05:55PM +0900, Gregory Brown wrote:
> On 1/12/07, Aaron Patterson <aaron_patterson@speakeasy.net> wrote:
> >Hi, I seem to be running in to some garbage collection weirdness.
> >Hopefully someone will have some insight for me....  My sample script
> >seems to leak Strings when I use shift on an Array, but not pop:
>
> http://recursive.ca/hutch/index.php?p=361
>

Thanks!
Feee221f9eb7818d90625ea141bfd60c?d=identicon&s=25 Bernard Kenik (bbiker)
on 2007-09-25 22:36
(Received via mailing list)
Aaron Patterson wrote:
>
> --
> Aaron Patterson
> http://tenderlovemaking.com/

The workaround to eliminate leakage with array.shift works except that
shift no longer returns the shifted element and instead returns nil

The following class allows shift to work normally without the leakage
... I know it is only a temporary work around until the ruby developers
get around to fix the c code

####  Array#shift ###############
class Array
  alias :orig_shift :shift
  def shift
    return nil if self.empty?
    ret = self[0]
    self[0] = nil
    self.orig_shift
    return ret
  end
end

###### code to show that the leakage has been eliminated
separator = "---"
o_count = Hash.new(0)
GC.start

ObjectSpace.each_object { |o| o_count[o.class] += 1 }
o_count.sort_by { |k,v| -v}.each { |k,v| puts "#{k}: #{v}" }
o_count = nil
puts separator

array = []
10.times { array << "foo" }
10.times { array.pop }  # Change this to shift to see a leak

o_count = Hash.new(0)
GC.start
ObjectSpace.each_object { |o| o_count[o.class] += 1 }
o_count.sort_by { |k,v| -v}.each { |k,v| puts "#{k}: #{v}" }
array = nil
o_count = nil

puts separator
array = []
10.times { array << "foo" }
10.times { array.shift }  # Change this to shift to see a leak

o_count = Hash.new(0)
GC.start
ObjectSpace.each_object { |o| o_count[o.class] += 1 }
o_count.sort_by { |k,v| -v}.each { |k,v| puts "#{k}: #{v}" }

__END__

#######  test results   only pertinent data shown
NEW shift method

        before pop      after pop
                        before shift       after shift
String: 1746            1764               1764
Array:  70                71                  72

OLD shift methed   --  Class Array commented out
        before pop      after pop
                        before shift       after shift
String: 1746            1764               1774
Array:  70                71                  72


##################  code to show that Array#shift behaves as described
in the ri documentation

class Array
  alias :orig_shift :shift
  def shift
    return nil if self.empty?
    ret = self[0]
    self[0] = nil
    self.orig_shift
    return ret
  end
end

a = (1..5).to_a

1.upto(10) do |i|
  x = a.shift

  puts "#{i}: \tx: #{x.inspect} \ta: #{a.inspect}"
end

__END__


1:   x: 1   a: [2, 3, 4, 5]
2:   x: 2   a: [3, 4, 5]
3:   x: 3   a: [4, 5]
4:   x: 4   a: [5]
5:   x: 5   a: []
6:   x: nil   a: []
7:   x: nil   a: []
8:   x: nil   a: []
9:   x: nil   a: []
10: x: nil   a: []
This topic is locked and can not be replied to.