16

xmlファイルを処理する本番環境で実行されているジョブがあります。xmlファイルは約4kで、サイズは8〜9GBです。

処理後、CSVファイルを出力として取得します。すべてのCSVファイルを取得している単一のファイルにマージするcatコマンドがあります。

Errno :: ENOMEM:メモリを割り当てることができません

on cat(バッククォート)コマンド。

以下にいくつかの詳細を示します。

  • システムメモリ-4GB
  • スワップ-2GB
  • Ruby:1.9.3p286

ファイルはとを使用して処理されnokogiriますsaxbuilder-0.0.8

ここには、4,000個のXMLファイルを処理するコードのブロックがあり、出力はCSV(xmlごとに1つ)に保存されます(申し訳ありませんが、会社のポリシーのb'cozで共有することは想定していません)。

以下は、出力ファイルを単一のファイルにマージするコードです

Dir["#{processing_directory}/*.csv"].sort_by {|file| [file.count("/"), file]}.each {|file|
            `cat #{file} >> #{final_output_file}`
}

処理中にメモリ消費のスナップショットを作成しました。メモリのほぼすべての部分を消費しますが、失敗することはありません。コマンドで常に失敗しますcat

バッククォートでは、十分なメモリを取得できない新しいプロセスをフォークしようとするため、失敗します。

あなたの意見とこれに代わるものを教えてください。

4

3 に答える 3

3

したがって、システムのメモリがかなり不足しているようで、シェルを生成して猫を呼び出すことは、残りのメモリが少なすぎるためです。

速度を落としてもかまわない場合は、小さなバッファーを使用して、ファイルをrubyにマージできます。これにより、シェルの生成が回避され、バッファーサイズを制御できます。

これはテストされていませんが、アイデアは得られます:

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
于 2013-02-26T14:35:24.457 に答える
3

おそらく物理メモリが不足しているので、それを再確認してスワップを確認してください(free -m)。スワップスペースがない場合は、スワップスペースを作成します

それ以外の場合、メモリに問題がない場合、エラーはシェルリソースの制限が原因である可能性があります。で確認できますulimit -a

それらはulimit、シェルリソースの制限を変更できるように変更できます(:を参照help ulimit)。

ulimit -Sn unlimited && ulimit -Sl unlimited

これらの制限を永続化するには、次のシェルコマンドで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
于 2016-07-10T02:53:03.600 に答える
2

同じ問題がありますが、代わりcatsendmailgem mail)でした。

gemをインストールすることで、ここで問題と解決策を見つけました。posix-spawn

gem install posix-spawn

そしてここに例があります:

a = (1..500_000_000).to_a

require 'posix/spawn'
POSIX::Spawn::spawn('ls')

今回は子プロセスの作成が成功するはずです。

関連項目:Oracleでアプリケーション・サブプロセスを作成するためのメモリ使用量の最小化。

于 2015-04-04T08:49:11.627 に答える