Errno :: ENOMEM:无法分配内存 - 猫

Ati*_*ith 14 ruby shell fork out-of-memory spawn

我有一个正在运行的工作,它处理xml文件.xml文件大约为4k,大小为8到9 GB.

处理完毕后,我们将CSV文件作为输出.我有一个cat命令,它将所有CSV文件合并到我得到的单个文件中:

Errno :: ENOMEM:无法分配内存

on cat(Backtick)命令.

以下是一些细节:

  • 系统内存 - 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}`
}
Run Code Online (Sandbox Code Playgroud)

我在处理期间拍摄了内存消耗快照.它几乎占用了内存的所有部分,但是,它不会失败.总是失败的cat命令.

我想,在反引号上它试图分叉一个新的进程,它没有获得足够的内存,所以它失败了.

请让我知道您的意见和替代方案.

Int*_*idd 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
Run Code Online (Sandbox Code Playgroud)