我有一个正在运行的作业,它处理xml文件。 xml文件大约为4k,大小为8到9 GB。
处理完毕后,我们将CSV文件作为输出。我有一个cat命令,它将所有CSV文件合并到我正在获得的单个文件中:
Errno :: ENOMEM:无法分配内存
on cat
(Backtick)命令。
以下是一些细节:
使用nokogiri
和saxbuilder-0.0.8
处理文件。
这里有一个代码块,它将处理4,000个XML文件,输出以CSV格式保存(每个xml 1个)(对不起,我不想在公司政策中分享它)。
下面是将输出文件合并为单个文件的代码
Dir["#{processing_directory}/*.csv"].sort_by {|file| [file.count("/"), file]}.each {|file|
`cat #{file} >> #{final_output_file}`
}
我在处理过程中拍摄了内存消耗快照。它几乎占用了内存的所有部分,但是它不会失败。
它总是在cat
命令上失败。
我想,在反击时,它会尝试派生一个新进程,但是没有足够的内存,所以它失败了。
请让我知道您的意见和替代方案。
答案 0 :(得分:3)
所以看起来你的系统内存运行相当低,并且产生一个shell +调用cat对于剩下的几个内存来说太多了。
如果您不介意失去一些速度,可以使用小缓冲区合并ruby中的文件。 这样可以避免产生shell,并且可以控制缓冲区大小。
这是未经测试但您明白了:
buffer_size = 4096
output_file = File.open(final_output_file, 'w')
Dir["#{processing_directory}/*.csv"].sort_by {|file| [file.count("/"), file]}.each do |file|
f = File.open(file)
while buffer = f.read(buffer_size)
output_file.write(buffer)
end
f.close
end
答案 1 :(得分:3)
您可能没有物理内存,因此请仔细检查并验证您的交换(free -m
)。如果您没有交换空间,create one。
否则,如果您的内存正常,则错误很可能是由shell资源限制引起的。您可以ulimit -a
检查它们。
可以通过ulimit
更改它们,这可以修改shell资源限制(请参阅:help ulimit
),例如
ulimit -Sn unlimited && ulimit -Sl unlimited
要使这些限制持久化,可以通过以下shell命令创建ulimit设置文件来配置它:
cat | sudo tee /etc/security/limits.d/01-${USER}.conf <<EOF
${USER} soft core unlimited
${USER} soft fsize unlimited
${USER} soft nofile 4096
${USER} soft nproc 30654
EOF
或使用/etc/sysctl.conf
全局更改限制(man sysctl.conf
),例如
kern.maxprocperuid=1000
kern.maxproc=2000
kern.maxfilesperproc=20000
kern.maxfiles=50000
答案 2 :(得分:2)
我遇到了同样的问题,但cat
代替sendmail
gem mail
。
我发现问题&amp;解决方案here安装posix-spawn
gem,例如
gem install posix-spawn
以下是示例:
a = (1..500_000_000).to_a
require 'posix/spawn'
POSIX::Spawn::spawn('ls')
这次创建子进程应该会成功。
另见:Oracle的Minimizing Memory Usage for Creating Application Subprocesses。