我有一个在生产环境中运行的工作,它处理 xml 文件。 xml 文件总计约 4k,大小为 8 到 9 GB。
处理后,我们得到 CSV 文件作为输出。我有一个 cat 命令,它将所有 CSV 文件合并到一个我得到的文件中:
Errno::ENOMEM: Cannot allocate memory
cat
(反引号)命令。
以下是一些细节:
- 系统内存 - 4 GB
- 交换 - 2 GB
- ruby :1.9.3p286
使用 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
命令上失败。
我想,在反引号上,它会尝试 fork 一个没有获得足够内存的新进程,因此它会失败。
请告诉我您的意见和替代方案。
最佳答案
因此看起来您的系统内存运行非常低,生成 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
关于ruby - Errno::ENOMEM:无法分配内存 - cat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15086133/