From: Eric Mahurin Date: 2007-07-20T11:48:39+09:00 Subject: Re: Array flatten memory "leak"? On 7/19/07, Ron M wrote: > After I use "flatten" on a big array; the garbage collector > seems to get pretty forgetful of what memory it's allowed > to free up. > > In both of the following scripts, the first two lines > create an array of many arrays; and then flatten them > back into a flat array. > > In both cases, the memory after creating this array > the scripts use about 20MB. After that, they > repeatedly pack and unpack an array. The script that > used "flatten" keeps growing quickly until it used > about 1/4 GB of memory. The script that flattened > the array by hand stays right about at 20MB. > > What could it be about flatten that makes the > garbage collector fail to see that it could be > re-using the memory of the pack/unpack loop? > > > ######################################################################### > # This unexpectedly grows to 200+MB. > ######################################################################### > a = (1..200000).map{|x| [x.to_s]};a.length > b = a.flatten.map{|x| x.to_i} ; b.length > puts `grep VmSize /proc/#{$$}/status` ######## under 20 MB > (1..100).each{|x| b.pack("I*").unpack("I*");} > puts `grep VmSize /proc/#{$$}/status` ######## WHOA GREW TO 1/4 GB. > > > ######################################################################### > # This stays at 20MB > ######################################################################### > a = (1..200000).map{|x| [x.to_s]};a.length > b = a.map{|x| x[0].to_i} ; b.length > puts `grep VmSize /proc/#{$$}/status` ######## under 20 MB > (1..100).each{|x| b.pack("I*").unpack("I*");} > puts `grep VmSize /proc/#{$$}/status` ######## still 20 MB > I isolated this a bit down by looking at the C code. The culprit in Array#flatten seems to be rb_ary_splice which also gets called when assigning an array slice (one form of Array#[]=). The culprit in Array#pack seems to be rb_str_buf_cat which also gets called from String#<