Ruby大数组和内存 [英] Ruby big array and memory

查看:80
本文介绍了Ruby大数组和内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个大数组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的所有这些数据吗?

解决方案

如果我使用 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     ...

配置文件以使用的131136字节开始,以使用的211394640字节结束,并且在运行中任何地方都没有减小大小,我们可以假定没有进行垃圾收集.

如果我随后添加一行代码,则将一个元素添加到数组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的数据,但是希望这可以为您提供证明它的工具.

I created a big array a, whose memory grew to ~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

After that, I "cleared" a, but the allocated memory didn't change until I killed the process. Is there something special I need to do to remove all these data which were assigned to a from the memory?

解决方案

If I use the Ruby Garbage Collection Profiler on a lightly modified version of your code:

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

I get the following output (on Ruby 1.9.3)(some columns and rows removed):

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     ...

The profile starts with 131 136 bytes used, and ends with 211 394 640 bytes used, without decreasing in size anywhere in the run, we can assume that no garbage collection has taken place.

If I then add a line of code which adds a single element to the array a, placed after a has grown to 5 million elements, and then has an empty array assigned to it:

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

This changes the profiler output to (some columns and rows removed):

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     ...

This profiler run now starts with 131 376 bytes used, which is similar to the previous run, grows, but ends with 2 280 168 bytes used, significantly lower than the previous profile run that ended with 211 394 640 bytes used, we can assume that garbage collection took place this during this run, probably triggered by our new line of code that adds an element to a.

The short answer is no, you don't need to do anything special to remove the data that was assigned to a, but hopefully this gives you the tools to prove it.

这篇关于Ruby大数组和内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆