ファイル全体を一度に丸呑みする場合と行ごとに丸呑みする場合の違いを確認するために、1,000,000 行を超える約 99 MB のファイルに対してテストを行いました。
greg-mbp-wireless:Desktop greg$ wc filelist.txt
1003002 1657573 99392863 filelist.txt
次のループを ruby ファイルに入れ、time コマンドを使用してコマンド ラインから実行しました。
IO.read(ARGV.first).lines { |l|
}
greg-mbp-wireless:Desktop greg$ time ruby test.rb filelist.txt
real 0m1.411s
user 0m0.653s
sys 0m0.169s
次に、行ごとに読み取るように変更し、それも時間を計りました。
IO.readlines(ARGV.first) { |l|
}
greg-mbp-wireless:Desktop greg$ time ruby test.rb filelist.txt
real 0m1.053s
user 0m0.741s
sys 0m0.278s
理由はわかりませんが、1 行ずつ読む方が高速です。これは、Ruby が最初の例でファイル全体を RAM にロードしようとしたときのメモリ割り当てに関連している可能性があります。または、ファイルごとに 1 回しかテストを行っていないため、異常だった可能性もあります。明示的なファイルサイズで a を使用するread
と、Ruby が事前に割り当てる必要がある量を知っているため、高速になる可能性があります。
そして、これをテストするために必要なのはそれだけでした:
fcontent = ''
File.open(ARGV.first, 'r') do |fi|
fsize = fi.size
fcontent = fi.read(fsize)
end
puts fcontent.size
greg-mbp-wireless:Desktop greg$ time ruby test.rb filelist.txt
99392863
real 0m0.168s
user 0m0.010s
sys 0m0.156s
どのくらい読む必要があるかを知ることは、かなりの違いを生むようです。
文字列バッファーのループに戻すと、次のようになります。
File.open(ARGV.first, 'r') do |fi|
fsize = fi.size
fi.read(fsize).lines { |l|
}
end
greg-mbp-wireless:Desktop greg$ time ruby test.rb filelist.txt
real 0m0.732s
user 0m0.572s
sys 0m0.158s
それはまだ改善です。
キューを使用し、ファイルの読み取りを担当するスレッドからそれを供給し、受信テキストを処理するすべてのプロセスからキューを消費した場合、全体的なスループットが高くなる可能性があります。