2012年6月25日月曜日

PHPでの文字列の有無の判定|empty()と!strlen()どっちがはやい?

久しぶりにPHPをいじっていて、関数の中に文字列がはいっていないかどうか判定する時って、empty()と!strlen()どっちでも使えるなあと思ってしまいました。
もちろんempty()は文字列変数の中身が"0"でも真になってしまうのですけれど、それさえ気をつければどちらでも良いはず。
昔書いたのをみてもそのときによってどっちも使っています。
PHPはこんなふうに、ある問題を解くのにいろんな方法が使えてしまいますよね。

ということで、今回は、ちょっとempty()と!strlen()のスピードを比べてみました。
早速結果です。

"if (!strlen($string))" VS "if (empty($string))どっちがはやい?"

unset($stringの場合);
!strlen()のかわりにempty()を使うことによる速度上昇の平均値: 99.72%

$string === falseの場合;
!strlen()のかわりにempty()を使うことによる速度上昇の平均値: 79.17%

$string = ''の場合;
!strlen()のかわりにempty()を使うことによる速度上昇の平均値: 69.79%

$string = 'hogehoge'の場合;
!strlen()のかわりにempty()を使うことによる速度上昇の平均値: 70.39%


基本的にempty()のほうが速いので、empty()をつかうと!strlen()に比べてどれだけ速いかを示すようにしました。常識なんでしょうかねぇ。
ちなみにこちらのサイトを参考というか、ここに出ているコードをそのまま使っています。追証実験ということで。環境によって差はあるんでしょうがスピードの差は歴然としていますよ。

理由としてはこちらのサイト
because empty() is a language construct built into the Zend engine, while strlen is implemented as a standard extension function. 
empty()はZendエンジンに組み込まれた言語だが、strlenは拡張機能として実装されているからだ
というふうに出ています。

そんなシビアなプログラムをするわけではないし、もしそうならならPHPじゃなくてもって感じもするので半ば自己満足です。

以下検証に用いたコード。

<?php
function test_strlen_vs_empty($string) {
    /* 基本的にはempty()のほうが速いですが、たまにstrlen()が速い時があります。100回の試行のうち1度有るか無いかくらい。その場合は$odditiesでカウントして、平均値はそれを除いてだしています。 */

    $oddities = 0;

    /* 変数が与えられないとき */
    if ($string == 'unset') {
        unset($string);
    }

    /* 試行は100回 */
    for ($i = 0; $i < 100; $i++) {
        /* タイマースタート */
        $start_time = microtime(true);

        /* empty()で100回チェック */
        for ($ii = 0; $ii < 100; $ii++) {
            /* Check if the string is empty() */
            if (empty($string)) {
            }
        }
        /* タイマーストップ */
        $end_time = microtime(true);

        /* empty()100回にかかった時間 */
        $time_for_empty = $end_time - $start_time;

        /* タイマースタート */
        $start_time = microtime(true);
        for ($ii = 0; $ii < 100; $ii++) {
            /* strlen()がfalseかどうか100回チェック */
            if (!strlen($string)) {
            }
        }

        /* タイマーストップ */
        $end_time = microtime(true);

        /*!strlen()100回にかかった時間*/
        $time_for_strlen = $end_time - $start_time;

        /* もし!strlen()のほうがempty()より速い時には記録 */
        if ($time_for_strlen < $time_for_empty) {
            $oddities++;
        } else {
            /* そうでなければempty()をつかうことで!strlen()にくらべてどのくらい速くなっているか%で加算 */
            $slowers_total += round(100 - (($time_for_empty / $time_for_strlen) * 100), 2);
        }
    }
    /* Output the results with an average taking into account any oddities that may have occurred */
    echo "<br />" . '!strlen()のかわりにempty()を使うことによる速度上昇の平均値: ' . round($slowers_total / (100 - $oddities), 2) . '%';
    if ($oddities) {
        echo "<br />" . '!strlen()のほうが速かった回数: ' . $oddities;
    }
}

echo "<br /><br />" . '"if (!strlen($string))" VS "if (empty($string))どっちがはやい?"' . "<br /><br />";
echo 'unset($stringの場合);';
test_strlen_vs_empty('unset');
echo "<br /><br />" . '$string === falseの場合;';
test_strlen_vs_empty(false);
echo "<br /><br />" . '$string = \'\'の場合;';
test_strlen_vs_empty('');
echo "<br /><br />" . '$string = \'hogehoge\'の場合;';
test_strlen_vs_empty('hogehoge');
?>

0 件のコメント:

コメントを投稿