PHP

【PHP】strposはpreg_matchよりどれくらい速いのか

前置き

PHPで、ある文字がある文字列の中に含まれているかどうかをチェックするときの話です。

正規表現でチェックする場合、 preg_match() を使用しますが、単純な文字列をチェックする場合にも preg_match() を使っていました。

が、preg_match()に関する公式ドキュメントを見てみると

ヒント
ある文字列が他の文字列内に含まれているかどうかを調べるためだけに preg_match() を使うのは避けた方が良いでしょう。 strpos() 関数を使うほうが速くなります。

とあります。
ではどれだけ差が出るのか、試してみました。

テスト用ソース

<?php

date_default_timezone_set('Asia/Tokyo');

$exec_cnt = 100;

echo sprintf('試行回数%s回%s', $exec_cnt, "\n\n");

$res = 0;
$start = microtime(true);
for ($n = 0; $n < $exec_cnt; $n++)
{
    $str = sprintf('今の数字は%sです', $n);
    if (preg_match('/55/', $n))
    {
        $res++;
    }
}
echo sprintf('preg_match ... res = %s (%s)%s', $res, sprintf('%.10f', (microtime(true) - $start)), "\n");

$res = 0;
$start = microtime(true);
for ($n = 0; $n < $exec_cnt; $n++)
{
    $str = sprintf('今の数字は%sです', $n);
    if (strpos($n, '55') !== false)
    {
        $res++;
    }
}
echo sprintf('strpos     ... res = %s (%s)%s', $res, sprintf('%.10f', (microtime(true) - $start)), "\n");

上の $exec_cnt でループ回数を指定して、かかった時間をそれぞれ計測してみます。
例えば上のソースの通り、100回ループした場合の出力結果は

試行回数100回

preg_match ... res = 1 (0.0001780987)
strpos     ... res = 1 (0.0000598431)

となり、100回の時点で strpos() のほうが preg_match() より約3倍速いです。以下、試行回数ごとの秒数です。
※実行したのはMacのローカル環境です

試行回数 preg_match()...p strpos()...s p/s
1000 0.0008649826 0.0005629063 1.53
10000 0.0074071884 0.0050859451 1.47
100000 0.0710110664 0.0543570518 1.31
1000000 0.6552450657 0.4806499481 1.36
...
100000000 70.5298569202 47.3726339340 1.49

試行回数が少ないときのほうが差は大きくなるようですが、strpos() のほうが preg_match()よりも、平均して1.4倍ほど速いようです。

やっぱり公式ドキュメントはしっかり読んだほうがいいですね。