XMLファイルを処理するジョブを本番環境で実行しています。 xmlファイルは約4kで、サイズは8〜9 GBです。
処理後、CSVファイルを出力として取得します。すべてのCSVファイルを1つのファイルにマージするcatコマンドがあります。
Errno :: ENOMEM:メモリを割り当てられません
cat
(バックティック)コマンド。
以下に詳細をいくつか示します。
ファイルは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しようとするため、失敗します。
あなたの意見とこれに対する代替案を教えてください。
したがって、システムのメモリがかなり少なくなり、シェル+を呼び出すcatを生成するだけでは、残りのメモリが少なすぎます。
少し速度を落としてもかまわない場合は、小さなバッファーを使用して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
物理メモリが不足している可能性があるため、再確認してスワップを確認してください(free -m
)。スワップスペースがない場合は、 create one を使用します。
それ以外の場合、メモリに問題がない場合、エラーはシェルリソースの制限が原因である可能性が高いです。 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
同じ問題がありますが、cat
の代わりにsendmail
(gem mail
)。
私は問題と解決策を見つけました ここ をインストールすることによってposix-spawn
gem、たとえば.
gem install posix-spawn
そしてここに例があります:
a = (1..500_000_000).to_a
require 'posix/spawn'
POSIX::Spawn::spawn('ls')
今回は子プロセスの作成は成功するはずです。
関連項目: アプリケーションサブプロセスを作成するためのメモリ使用量の最小化 Oracle。