最近、Rubyの大規模なCSVファイルとやりとりする問題が発生しました。明らかな解決策は、このようなファイルの代わりにデータベースにこのデータをホストすることですが、私の問題の根本を見つけたいと思います。Ruby CSVの解析メモリ割り当て
私がやりとりしているデータはあまり大きくありません。約43Mデータポイントです。寸法は8760x5000です。私は実際にこの全体のCSVファイルを読み込む必要があります。そこで、いくつかのマッピング操作を実行してから、新しいファイルにそれをダンプすることができます。
私は両方を試してみた:
CSV.foreach("file") do |row|
master_arr << row
end
と
master_arr = CSV.read("file")
これらのオプションの両方がメモリ割り当てエラーをトリガ - 割り当てられた十分なメモリがない旨。通常、次のようなエラーが表示されます。
C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1798:in `gets': failed to allocate memory (NoMemoryError)
from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1798:in `block in shift'
from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1796:in `loop'
from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1796:in `shift'
from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1738:in `each'
from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1122:in `block in foreach'
from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1273:in `open'
from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1121:in `foreach'
from compilation.rb:23:in `<main>'
これはなぜ問題なのでしょうか。 CSVファイルは約600MBで、私のマシンのリソースを見ると、RAM消費量は、障害が発生する前に約1GBだけ増加します。この間、まだ約10GBの空きRAMがあります。私は、同じサイズの配列を作成し、ランダムなデータを移入した場合
:
arr1 = Array.new(8760){|i| i+0.111111111111}
arr2 = Array.new(5000){arr1}
メモリに格納何ら問題がないものの場合は、CSVファイルに書き込むしようと、私はメモリを受け取ります割り当てエラー。私はCSV.rbファイルを調べましたが、これを引き起こす何かを見つけることができませんでした。
奇妙なことは、これが動作することである:
for i in 0..4999
CSV.foreach("file") do |row|
master << row
break if master_arr.length > 3000
end
end
が、私は二つにファイルを分割しようとした場合、これは動作しません:
CSV.foreach("file_1_2") do |row|
master_arr << row
end
CSV.foreach("file_2_2") do |row_1|
master_arr << row_1
end
それはされていない、これらのオブジェクトのようなものです記憶から解放されましたが、私は何が起こっているのか正確には分かりません。私が言ったように、これは大きなファイルであり、最良の選択肢ではないことは分かっていますが、これは一回限りの解決策であり、問題なく使用できるリソースがあります。
64ビットRubyを使用していますか?それは1GBだけだと確信していますか? – tadman
まあ...これはかなり恥ずかしいですが、それは実際問題でした。 Rails用にパッケージ化されたインストーラを使用したときは、32ビットのインスタンスが付属していたと思います。私はこれについても考えなかったとは信じられません。 –