ruby使ってるおとこの人って・・・

これってどっちが早いんだろう - すがブロ
「system関数から実行したgrepコマンドの方が、ruby内でパターンマッチするより早い」的なことが書いてあって、しかもそれは「当たり前」のことらしい。個人的な感覚としては、外部プロセス呼び出すオーバーヘッドの方が明らかに大きいだろうと思ってたのでかなり衝撃だった。のでPerlで試してみよう。

use strict;
use warnings;
use Benchmark qw(timethese cmpthese);

my $file    = 'Book1.csv';
my $tmpfile = 'tmp.out';
cmpthese(timethese(100, {
  native_grep => sub{
    system("grep 'even if' $file > $tmpfile");
    open(F, $tmpfile);
    print STDERR while (<F>);
    close(F);
  },
  pureperl_grep => sub{
    open(F, $tmpfile);
    while(<F>){
      print STDERR if /even if/;
    }
    close(F);    
  }
}));

できた。perl v5.8.8 built for cygwin-thread-multi-64intでの実行結果

$ perl grep.pl 2>/dev/null
Benchmark: timing 100 iterations of native_grep, pureperl_grep...
native_grep: 53 wallclock secs ( 2.08 usr  5.64 sys + 10.01 cusr 17.78 csys = 35.51 CPU) @ 12.96/s (n=100)
pureperl_grep:  8 wallclock secs ( 2.09 usr +  4.78 sys =  6.87 CPU) @ 14.55/s (n=100)

                Rate   native_grep pureperl_grep
native_grep   13.0/s            --          -11%
pureperl_grep 14.5/s           12%            --

Pure Perlの方が早いよなあ・・・。Cygwinだからかと思って、某OS*1でも実行してみた。

# perl grep.pl 2>/dev/null
Benchmark: timing 100 iterations of native_grep, pureperl_grep...
native_grep:  5 wallclock secs ( 1.49 usr  0.98 sys +  0.90 cusr  0.70 csys =  4.07 CPU) @ 40.49/s (n=100)
pureperl_grep:  3 wallclock secs ( 1.88 usr +  0.86 sys =  2.74 CPU) @ 36.50/s (n=100)

                Rate pureperl_grep   native_grep
pureperl_grep 36.5/s            --          -10%
native_grep   40.5/s           11%            --

やっぱりPure Perlの方が・・・と思ったら逆になった。Cygwinのオーバーヘッドなのか・・・。
プロファイルも取ってみたけど、unknownな情報が多い上にblogに書けないことが多すぎるからあまり深追いはしないでおこう。Cygwinでプロファイルって取れるんだろうか・・・

追記

元エントリーでシステムコールのことが突っ込まれてる・・・。まあ、forkしてexecするからシステムコールと言えなくもないか。それよりも、キーワード「システムコール」が意味不明な説明になってるので、誰か直してくれないかなあ。暇だったら直しておこう。

*1:perl, v5.8.2 built for ***。仕事用マシンなので秘密・・・