5

我创建了一个大数组a,其内存增长到 ~500 MB:

a = []

t = Thread.new do 
  loop do
    sleep 1
    print "#{a.size} "
  end
end

5_000_000.times do
  a << [rand(36**10).to_s(36)]
end

puts "\n size is #{a.size}"
a = []

t.join

之后,我“清除”a了,但分配的内存在我终止进程之前没有改变。a我需要做一些特别的事情来从内存中删除所有这些分配给的数据吗?

4

2 回答 2

4

如果我在稍微修改过的代码版本上使用Ruby Garbage Collection Profiler :

GC::Profiler.enable
GC::Profiler.clear

a = []
5_000_000.times do
  a << [rand(36**10).to_s(36)]
end

puts "\n size is #{a.size}"
a = []

GC::Profiler.report

我得到以下输出(在 Ruby 1.9.3 上)(删除了一些列和行):

GC 60 invokes.
Index    Invoke Time(sec)       Use Size(byte)     Total Size(byte)     ...
    1               0.109               131136               409200     ...
    2               0.125               192528               409200     ...
  ...
   58              33.484            199150344            260938656     ...
   59              36.000            211394640            260955024     ...

配置文件以使用的 131 136 字节开始,以使用的 211 394 640 字节结束,在运行中的任何地方都没有减少大小,我们可以假设没有发生垃圾收集。

如果我然后添加一行代码,将单个元素添加到数组 a 中,放置在 a 增长到 500 万个元素之后,然后分配一个空数组:

GC::Profiler.enable
GC::Profiler.clear

a = []
5_000_000.times do
  a << [rand(36**10).to_s(36)]
end

puts "\n size is #{a.size}"
a = []

# the only change is to add one element to the (now) empty array a
a << [rand(36**10).to_s(36)]

GC::Profiler.report

这会将分析器输出更改为(删除了一些列和行):

GC 62 invokes.
Index    Invoke Time(sec)       Use Size(byte)     Total Size(byte)     ...
    1               0.156               131376               409200     ...
    2               0.172               192792               409200     ...
  ...
   59              35.375            211187736            260955024     ...
   60              36.625            211395000            469679760     ...
   61              41.891              2280168            307832976     ...

此分析器运行现在以使用的 131 376 字节开始,这与之前的运行类似,但会增长,但以使用的 2 280 168 字节结束,显着低于之前以使用 211 394 640 字节结束的分析器运行,我们可以假设垃圾收集在此运行期间发生,可能是由我们向 a 添加元素的新代码行触发的。

简短的回答是否定的,您不需要做任何特别的事情来删除分配给 a 的数据,但希望这可以为您提供证明它的工具。

于 2012-08-11T20:16:14.913 回答
4

你可以打电话GC.start(),但你可能不想。例如,请参阅:Ruby 垃圾收集,在 Stack Overflow 上进行讨论。基本上,我会让垃圾收集器自己决定何时运行,除非你有令人信服的理由强制它。

于 2012-08-11T07:14:23.550 回答