すがブロ

sugamasaoのhatenablogだよ

これってどっちが早いんだろう

ふと考えてみたんだけど

あるファイル(以下A)から特定の値(以下X)が入っている行だけ抽出して、その結果を処理したい、という時はどっちが早いのか。どっちも大差ないものなんだろうか。
※ただし、プログラムは Ruby から起動しなくてはいけないものとする

  1. Ruby からキックされ、systemメソッド(システムコール)でAから grep で抜き出した結果をファイルへ出力。その結果のファイルを Ruby で読み込む
  2. Ruby で A を読み込み、 if 文で該当行だけ抜き出して、必要な行のみ取得する。

これってどっちが早いんだろうね。ネイティブなコマンドを使ってる分、1. の方がはやそうだけど、処理のスマートさで行ったら 2. だよね*1
というわけで、実験してみる。

こんなデータでやってみたよ

2000/12/16,Hirai Ken,8th,why
2000/5/10,Hirai Ken,9th,LOVE OR LUST
2000/1/19,Hirai Ken,10th,even if
2000/12/16,Hirai Ken,8th,why
2000/5/10,Hirai Ken,9th,LOVE OR LUST
2000/1/19,Hirai Ken,10th,even if
:

こんな感じの3つのデータが繰り返し現れる CSV ファイルを用意した。
これを合計1万行まで繰り返したのが A というファイル。
1万行のデータから 'even if' の含まれている行を調べてして、何行抽出されたかを出力する。
なるべく差のでないようなソースを心がけてみたのだけど……どうだろうか。

検証ソース:システムコールを使う版
FILE_NAME='Book1.csv'
TEMP_FILE='system.tmp'

system("grep 'even if'  #{FILE_NAME} > #{TEMP_FILE}")

File.open(TEMP_FILE, 'r') do |file|
  puts file.readlines.size
end
検証ソース:Rubyだけで処理する版
FILE_NAME='Book1.csv'

list=[]

File.open(FILE_NAME, 'r') do |file|
  file.each do |line|
    list << line if line =~ /even if/
  end
end

puts list.size

実験結果

[masa@www]~/sokutei% time ruby ./system.rb
33320
ruby ./system.rb 0.06s user 0.03s system 99% cpu 0.091 total
[masa@www]~/sokutei% time ruby ./ruby_onry.rb
33320
ruby ./ruby_onry.rb 0.37s user 0.12s system 97% cpu 0.509 total

どうみてもシステムコールの方が早いです。当たり前です。本当にありがとうございました。
システムコールで実装した方は中間ファイルを吐くので、その分で差が出てくるかと思ったら全然そんなことなかった_| ̄|○

続き

こっちにかいたよー
http://d.hatena.ne.jp/seiunsky/20071107/1194448571

*1:Ruby で書くことを前提としているため