From: Robert Dober Date: 2007-10-25T06:03:08+09:00 Subject: Re: pop/push, shift/unshift On 10/24/07, Bob Hutchison wrote: > Hi, > > On 24-Oct-07, at 3:09 PM, Robert Dober wrote: > > > Sorry for replying to my own post, can somebody confirm please that > > the following code proves that Array#shift does not leak? > > Thx in advance > > def count > > i = 0 > > ObjectSpace.each_object{ i += 1 } > > i > > end > > > > a = [] > > 10.times do > > 10_000.times do > > a << "a" > > a.shift > > end > > ObjectSpace.garbage_collect > > p count > > end > > 381 > > 382 > > 382 > > 382 > > 382 > > 382 > > 382 > > 382 > > 382 > > 382 > > > > Robert > > > > > Try it this way: > > class Thing > end > > def count > i = 0 > ObjectSpace.each_object(Thing){ i += 1 } > i > end > > a = [] > 10.times do > 10_000.times do > a << Thing.new > end > ObjectSpace.garbage_collect > 10_000.times do > a.shift > end > ObjectSpace.garbage_collect > puts "count(1): #{count} size: #{a.size}" > a.push(nil).pop > ObjectSpace.garbage_collect > puts "count(2): #{count} size: #{a.size}" > > 10_000.times do > a << Thing.new > end > ObjectSpace.garbage_collect > 10_000.times do > a[0] = nil # <<<<<< !!!! > a.shift > end > ObjectSpace.garbage_collect > puts "count(3): #{count} size: #{a.size}" > end > > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > count(1): 10000 size: 0 > count(2): 0 size: 0 > count(3): 0 size: 0 > > ---- > Bob Hutchison -- tumblelog at http:// > www.recursive.ca/so/ > Recursive Design Inc. -- weblog at http://www.recursive.ca/ > hutch > http://www.recursive.ca/ -- works on http://www.raconteur.info/ > cms-for-static-content/home/ > > Amazing Bob, it has nothing to do with nil though, but with the assignment to a[0] change a[0] = nil to a[0]=42, you get the same results. You can even do the following def count i = 0 ObjectSpace.each_object{ i += 1 } i end a = [] 10_000.times do a << Object.new end ObjectSpace.garbage_collect 10_000.times do a.shift end ObjectSpace.garbage_collect puts "count(1): #{count} size: #{a.size}" a.push(nil).pop ObjectSpace.garbage_collect puts "count(2): #{count} size: #{a.size}" 10_000.times do a << Object.new end ObjectSpace.garbage_collect 10_000.times do a[0] = Object.new a.shift end ObjectSpace.garbage_collect puts "count(3): #{count} size: #{a.size}" count(1): 10386 size: 0 count(2): 389 size: 0 count(3): 392 size: 0 There remains one thing to be clarified, is this really a bug? I do not think so, I just ran this until I got 200 points on my terminal :-0 a = [] loop do a << Array.new( 1_000_000){ Object.new } a.shift $stdout.print "." $stdout.flush end on my Zenwalk box memory is allocated and released regualrely, I doubt if ObjectSpace is the right tool to use. Anyway forgive me to be blunt but everybody should just use Array#shift. Cheers Robert