正規表現のベンチ細々ととってみました。

正規表現でのパフォーマンスというのは非常に気を使う箇所ですが、
早くなるようにと慣習的にやっている事が実際どの程度違うのかは知らなかったので、
細々とベンチとってみました。

前提
$STRの内容は

my $STR = "ABCDEFG";

です。


其の1 - ?:有り無し

「()の中身は後方参照用($1,$2)に保持される。それを回避するには先頭に?:を付けると早くなる。」
と思っていましたが・・・

コード

sub foo { $STR =~ /^(AB|CD)/ }
sub bar { $STR =~ /^(?:AB|CD)/ }

結果

Benchmark: timing 1000000 iterations of ?:無し, ?:有り...
    ?:無し:  2 wallclock secs ( 1.85 usr +  0.00 sys =  1.85 CPU) @ 540540.54/s (n=1000000)
    ?:有り:  1 wallclock secs ( 0.67 usr +  0.00 sys =  0.67 CPU) @ 1492537.31/s (n=1000000)
            Rate ?:無し ?:有り
?:無し  540541/s     --   -64%
?:有り 1492537/s   176%     --

やはりかなり違いますね。間違ってなかった!


其の2 - qrで予めコンパイル

正規表現を毎回評価するのではなく、予めコンパイルしておくと早くなる。」
と思っていましたが・・・

コード

my $STR_RGX = qr/^ABC/;
my $RGX_STR = "^ABC";
sub foo { $STR =~ $STR_RGX }
sub bar { $STR =~ /$RGX_STR/ }

結果

Benchmark: timing 1000000 iterations of 事前, 毎回...
      事前:  1 wallclock secs ( 1.22 usr +  0.00 sys =  1.22 CPU) @ 819672.13/s (n=1000000)
      毎回:  2 wallclock secs ( 1.67 usr +  0.00 sys =  1.67 CPU) @ 598802.40/s (n=1000000)
         Rate 毎回 事前
毎回 598802/s   -- -27%
事前 819672/s  37%   --

出ました。中々の差です。
都合によりますが、出来るものは事前にしといて損はないですな。


其の3 - 範囲指定とメタ文字

\dと[0-9]の使い分けを特に意識はしてなかったんですが、
万が一速度に差があるなら統一しようと思いまして、調べました。


コード

sub foo { $STR =~ /[0-9]/ }
sub bar { $STR =~ /\d/ }

結果

Benchmark: timing 1000000 iterations of メタ文字, 範囲指定...
  メタ文字:  0 wallclock secs ( 0.67 usr +  0.00 sys =  0.67 CPU) @ 1492537.31/s (n=1000000)
  範囲指定:  1 wallclock secs ( 0.70 usr +  0.00 sys =  0.70 CPU) @ 1428571.43/s (n=1000000)
              Rate 範囲指定 メタ文字
範囲指定 1428571/s       --      -4%
メタ文字 1492537/s       4%       --

変わんないですね。ま、どちらでも良いと。


其の4 - 範囲指定とパイプ

結構、[A-C]で済む所をわざわざ(A|B|C)と
考えないで書いてしまう事があります。

どの程度影響を及ぼすのかという事で。

コード

sub foo { $STR =~ /[A-C]/ }
sub bar { $STR =~ /(A|B|C)/ }
sub fuga { $STR =~ /(?:A|B|C)/ }

結果

Benchmark: timing 1000000 iterations of ?:無し, ?:有り, 範囲指定...
    ?:無し:  1 wallclock secs ( 1.41 usr +  0.00 sys =  1.41 CPU) @ 709219.86/s (n=1000000)
    ?:有り:  1 wallclock secs ( 0.60 usr +  0.00 sys =  0.60 CPU) @ 1666666.67/s (n=1000000)
  範囲指定:  0 wallclock secs ( 0.43 usr +  0.00 sys =  0.43 CPU) @ 2325581.40/s (n=1000000)
              Rate   ?:無し   ?:有り 範囲指定
?:無し    709220/s       --     -57%     -70%
?:有り   1666667/s     135%       --     -28%
範囲指定 2325581/s     228%      40%       --

やはり結構差がでました。


感想

お作法に則って素直にわかりやすく書いたほうが結果として
読みやすくて速い気がします。