【问题标题】:How to force Ruby release memory to OS如何强制 Ruby 向操作系统释放内存
【发布时间】:2015-05-03 19:09:35
【问题描述】:

正如标题,我有一个处理大量数据的 ruby​​ 程序。该程序占用了所有内存,其中调用了系统命令hostname, 并且发生了错误

Cannot allocate memory - hostname

我试过GC.start 还是不行。

那么如何强制 ruby​​ 释放未使用的内存呢?

好的,这是别人的测试代码,最后报错显示big_var已经被回收了。但是内存仍然没有释放。

require "weakref"
def report
  puts "#{param}:\t\t Memory " + `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`
      .strip.split.map(&:to_i)[1].to_s + 'KB'
end
big_var = ""
#big_var = WeakRef.new(big_var)

report
big_var = 1_000_000.times.map(&:to_s)
report

big_var = WeakRef.new(big_var)

GC.start

sleep 1
report

p big_var.length

#Memory 7508KB
#Memory 61516KB
#Memory 53700KB
#test.rb:20:in `<main>': Invalid Reference - probably recycled (WeakRef::RefError)

好的,我试过了,我不明白为什么在我做了$big_var=nilGC.start之后GC.stat[:heap_used]仍然那么大

puts GC.stat[:heap_used]
$big_var = []
  5000000.times { |i|
    $big_var << i.to_s
  }
puts GC.stat[:heap_used]
$big_var = nil
puts GC.stat[:heap_used]
GC.start
puts GC.stat[:heap_used]

#70
#12286
#12286
#9847    

另外,我使用 Ruby 2.1 和 CentOS 6.4

【问题讨论】:

标签: ruby memory release


【解决方案1】:

我可以看到垃圾收集是由WeakRef 类完成的,如文档所述。这是我试图证明这一点的尝试:

require 'objspace'
require "weakref"

big_var = ""
puts "memory size: #{ObjectSpace.memsize_of big_var}"

big_var = 1_000_000.times.map(&:to_s)
puts "memory size: #{ObjectSpace.memsize_of big_var}"

big_var = WeakRef.new(big_var)
GC.start

puts "memory size: #{ObjectSpace.memsize_of big_var}"

输出

[shreyas@arup_ruby (master)]$ ruby a.rb
memory size: 40
memory size: 11636312
memory size: 40
[shreyas@arup_ruby (master)]$

看方法:memsize_of.

【讨论】:

  • 是的,即使将 big_var 设置为 nil,我也可以获得相同的输出。但是内存还是没有释放~~~
  • 我认为 memsize_of 只是 big_var 现在引用的内存大小。但是它之前引用的大内存仍然被 Ruby 持有,没有被释放。
  • @sou Ok 可能是……我不确定:/
猜你喜欢
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
  • 2015-07-15
  • 2019-11-02
相关资源
最近更新 更多