我有一个ruby脚本,该脚本将大量数据加载到内存中,然后需要添加 shell 以对该数据执行任务。但是有时候,数据如此之大,以至于脚本在交换中运行,在这种情况下,脱 shell 给了我Errno::ENOMEM
错误。
这是重现该问题的脚本:
def current_process_ram
pid, size = `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)
size / 1000
end
def display_current_process_ram
"Current RAM: #{current_process_ram}"
end
puts display_current_process_ram
array = []
one_gig = 14_000_000
0.upto(one_gig * 2.5) do
array << '12345'
end
sleep 2
`ls`
puts display_current_process_ram
运行脚本之前的
htop
:脚本运行时的
htop
:产生的错误:
deploy@vagrant-ubuntu-trusty-64:~/statusmachine$ ruby test.rb
Current RAM: 7
test.rb:19:in ``': Cannot allocate memory - ls (Errno::ENOMEM)
from test.rb:19:in `<main>'
它在Ubuntu服务器“trusty tahr” VM上运行。
我的问题
为什么会出现
Errno::ENOMEM
错误?我希望系统调用能够正常工作,因为我有足够的交换空间来执行它。编辑:如果我将脚本更改为仅使用1个演出,则在放炮弹时不会爆炸。
编辑2:当我掏出 shell 时,仍然有很多交换可以执行系统调用,因此不应该发生
Errno::ENOMEM
。编辑3:澄清了我的问题。
最佳答案
因为Ruby无法分配足够的内存。
当您使用典型的Ruby(又称KRI,MRI,YARV)时,Ruby的内存管理很难(IMHO)。
这是一篇可能对您有帮助的文章:
http://adamniedzielski.github.io/blog/2014/02/05/fighting-paperclip-errno-enomem-error/
本文中的关键思想是:“要创建子进程,可用内存必须大于父进程占用的内存。”
本文中的解决方案是切换到使用posix-spawn
gem:
https://github.com/rtomayko/posix-spawn