php勉強会じゃなくて懇親会 (と preg v.s. mb_ereg)

http://events.php.gr.jp/event.php/event_show/29

行ってきました。LT 3分 x 29人という珍しい形式で、大成功だったんじゃないかと思います。どれも面白い話で、すぐに次の話題になっちゃうのがひたすらもったいなかった。正直、もうあと3時間くらい欲しいくらいでした。幹事のLINDさんありがとうございました & おつかれさまでした。

自分はというと、ちゃんとした自己紹介もできず、テキストファイル表示しただけの適当な内容でだいぶ反省です。資料を公開されている方が多いので、ちょっと追試してみました。

意外にpreg_matchが遅い場面が!?

preg_match, mb_ereg, eregを比べると、なんとなくpreg_matchが高速で機能も豊富なイメージを持つ方は多いんじゃないかと思います。しかし、意外にそうでもなかった! …という話でした。

当日とは違い、以下のようなコードで正規表現マッチの速さを比較してみました。

$j = 0;
$begin = microtime(true);
foreach (range(1, 1000000) as $i) {
    if (preg_match('/abc/', sha1($i))) {
        $j++;
    }   
}
$end = microtime(true);

比較結果。なんとなくmb_eregが基準で、数字が小さいほど速い。ここではphp5のみの比較です。あと、はてなテーブル記法の都合で "|" を ":" と書いてます。

regex preg_match mb_ereg ereg preg/mb ereg/mb
abc 4.91 sec 4.49 sec 5.44 sec 109% 121%
(abc) 5.73 sec 4.75 sec 4.76 sec 121% 100%
abc:def 12.53 sec 5.93 sec 11.68 sec 211% 197%
(abc:def) 15.06 sec 6.16 sec 12.27 sec 244% 199%
abc:def:ghi 14.48 sec 6.1 sec 14.13 sec 237% 232%
(abc:def:ghi) 17.44 sec 6.12 sec 15.28 sec 285% 250%
a*b?c+ 8.81 sec 8.68 sec 7.42 sec 101% 85%
regex preg_replace mb_ereg_replace ereg_replace preg/mb ereg/mb
abc 4.96 sec 6.09 sec 5.34 sec 81% 88%
abc:def 10.87 sec 8.01 sec 12.26 sec 136% 153%
abc:def:ghi 12.87 sec 7.42 sec 14.48 sec 173% 195%
  • pregの "|" でパターンをつないでいくとすごい遅くなる
  • mbと比べて2倍くらい時間がかかる。
    • 1行がもっと長ければ10倍くらい変わる (当日の例は長いテキストでした)
  • (ちょっと謎だけど) captureつきになったときの遅さもpregが弱い??
  • eregはよくわからん

"a*b?c+" の結果を見るに、「pregよりmb_eregのほうが速い」というよりも「pregは苦手なパターンがある」といった方がイメージ的にもあう気がしました。ちなみに id:moriyoshi に以前聞いた話によると、PCREのキャプチャが遅いのはphp側のbindingがイケてないらしいです。なのでPCREと鬼車の比較にはなってないかな。

これって正規表現エンジン業界だとけっこう常識だったりするのでしょうか?

あと

$array[($offset = -5) % count($array)] とか HMM 勉強会とか後楽園飲みとかソース読むならGNUよりBSDとか、時間がすぎるのがほんとあっという間でした。