3

ふるいにかけたいログファイルがいくつかあります。内容は、ログ ファイルで期待されるとおりです。コンマで区切られた多数の単一行のテキストです。ファイルはそれぞれ約 4 ギガバイトです。File.each_line または foreach は、そのうちの 1 つに約 20 分かかります。

単純な foreach は単純に見える (そして遅い) ため、2 つの別々のスレッドがどこから開始するかだけを指定できれば、同じファイルで作業できるのではないかと考えていました。しかし、私の(限られた)知識に基づいて、これが可能かどうかを判断することはできません.

任意の行でファイルの読み取りを開始する方法はありますか?

4

4 に答える 4

3

ファイル全体を一度に丸呑みする場合と行ごとに丸呑みする場合の違いを確認するために、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

それはまだ改善です。

キューを使用し、ファイルの読み取りを担当するスレッドからそれを供給し、受信テキストを処理するすべてのプロセスからキューを消費した場合、全体的なスループットが高くなる可能性があります。

于 2010-11-05T04:15:52.060 に答える
2

ファイルの特定の行から始めたい場合は、最後までシェルアウトすることをお勧めします。

excerpt = `tail -m +5000 filename.log`

これにより、5000行目からファイルの終わりまでのfilename.logの内容がわかります。

于 2010-11-09T17:32:42.877 に答える
1

行の場合、少し難しいかもしれませんが、ファイル内で特定のバイトを探すことができます。

IO#seek (リンク)IO#pos (リンク)の両方を使用すると、ファイル内の特定のバイトをシークできます。

于 2010-11-05T03:05:52.053 に答える
0

まだ行っていない場合はfaster_csvを試してみてください。それでも遅すぎる場合は、次のようにcでネイティブ拡張機能を持つものを使用してください - http://github.com/wwood/excelsior

于 2010-11-05T05:41:43.820 に答える