短いバージョン: Rubyを使用して高性能を維持しながらSTDIN(またはファイル)charからcharを読み取る方法は? RubyのI/Oパフォーマンス - charによるファイルcharの読み取り
(問題は、おそらく特定のルビーではありませんが)ロングバージョン: 私は、パイプで連結されたテキストデータから読み取る見つけ、それに番号を収集し、いくつかの処理を行う必要があります小さなユーティリティを設計していますルビーを学びながら。
cat huge_text_file.txt | program.rb
input > 123123sdas234sdsd5a ...
output > 123123, 234, 5, ...
私はについての私の懸念を持っていたのに(テキスト入力は、巨大な(ギガバイト)であるかもしれないし、それが改行や空白文字が含まれていない可能性があります(任意の数字以外の文字が区切りである)ので、私は読んcharで文字を行いましたパフォーマンス)、それはこのようにすることは信じられないほど遅いことがわかります。
900KBの入力ファイルでcharをcharで読み込むだけで約7秒かかります!
while c = STDIN.read(1)
end
改行でデータを入力して1行ずつ読み込むと、同じファイルが100倍高速に読み込まれます。
while s = STDIN.gets
end
それはSTDIN.read(1)
でパイプから読み取りが任意のバッファリングと、読み取りが起こるたびに関与しないように、ハードドライブがヒットしたようだ - しかし、それはOSによってキャッシュされるべきではないのですか?
STDIN.gets
charが '\n
'になるまで内部的にcharを読み込みませんか?
Cを使用すると、バッファウィンドウで分割された数値を処理する必要がありますが、Ruby用の洗練されたソリューションのようには見えません。では、これを行う正しい方法は何ですか? Pythonで同じファイルを読み込む
P.Sタイミングは:
for line in f:
line
f.close()
時間を実行すると、0.01秒です。
c = f.read(1)
while c:
c = f.read(1)
f.close()
実行時間は0.17秒です。
ありがとうございます!
ここで問題と思われるのはIOだけでなくガベージコレクタです。 'read(1)'を使用すると、ファイルの各バイトに新しいStringオブジェクトが作成されます。 temp文字列を作成し、 'read'を呼び出すたびにそれを再利用すると、より良い結果が得られるかもしれません。したがって、最初に 'buffer =" "'を実行すると、あなたのループ内のreadを 'STDIN.read(1、buffer)'として呼び出すことができます。 – matt
@mattの提案に感謝します!私はそれを試みました、それは少し速いです。 'cat'からパイプされた900Kファイルで、' buffer = ''の 'STDIN.read(1)'の実行時間は平均4.6秒です。 STDIN.read(1、buffer) ' - STDIN.getsのための4.5秒 - 0.08秒。私はSSDからHDDにすべてのものを移動してみました。私は、入力ファイルはOSによってキャッシュされなければならないと思っています。 – epsylon
私はPythonで同じものを計時し、 'for line in file:line'は0.01秒です。while while c:c = file.read(1)'は0.17秒です。しかしチャンクで読むのはまだ10倍以上高速です。 – epsylon