As the title, I have a ruby program deal with a large term of data. The program took all memory and there is a calling of system command hostname
in it,
and an error happened
Cannot allocate memory - hostname
I've tried GC.start
and it doesn't work.
So how can I force ruby to release the memory unused?
OK, this is a test code from other people, and the error at last shows that big_var
has been recycled. However the memory is still not released.
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)
OK, I tried things blow and I do not understand why the GC.stat[:heap_used]
is still that large after I did $big_var=nil
and GC.start
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
In addition, I use Ruby 2.1 and CentOS 6.4
I can see the garbage-collection is done by WeakRef
class as documented. here is my try to prove this :
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}"
output
[shreyas@arup_ruby (master)]$ ruby a.rb
memory size: 40
memory size: 11636312
memory size: 40
[shreyas@arup_ruby (master)]$
Look at the method : memsize_of
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With