Wonderful! WordPress

php8 で使えるようになった str_contains と strpos

php8 で追加され使えるようになった str_contains
文字列の中に指定した文字列が存在しているか確認する条件式、
if ( false !== strpos( $target, ‘search-string’ ) )
は使用頻度の高いものなので、その代替となる str_contains はかなり気になっていた関数なのであった。

strpos よりも高速に動いてくれるのであれば、喜ばしいのではあるが・・・。
str_contains は、検索文字列が存在した場合、その位置を返す strpos とは違い、存在の有無を boolean で返すだけのよりシンプルなもの。とはいっても、やっていることは同じようなことであろうから、速度的にはあまり期待はせずにいたのではある。

ベンチマークテスト

ということで、さっそくベンチをやってみた。
自分は鳥見人なので、鳥種をリストにしたファイルを持っているので、テストのサンプルにはそれを使うことにする。鳥の学名と種名がセットになったリストで、ランダムに選出した種名の基名にあたる部分を、これまたランダムに選出した行に含まれるか検索させた。ちなみに鳥データは 10518種となる。

<?php
    // テストで使う文字列の入ったファイルの読み込みでどうでもいい部分
    // bird_list.txt 鳥種リストは一行一種で、学名,英名となっている、全10518種 
    $tarfile = './bird_list.txt';
    $birds = file( $tarfile );
    $bname = array();

    echo '<p>bird count : ' . count ( $birds ) . '</p>'; 
    if ( $birds ) {
        foreach ( $birds as $val ) {
            $bele = explode ( ',', $val );
            if ( isset ( $bele[1] ) ) {// $bele[1]は英名で、スペースで分割された最後が基本名
                $tmpname = explode( ' ', $bele[1] );
                $bname[] = end( $tmpname );
            }
        }
    }
    // ここまで下準備

    // ここからベンチマーク
    echo '<p> strpos 10,518回 x 5</p>';

    for ( $j = 1; $j < 6; ++$j ) {
        $ansnum = array( 0, 0 );
        $gettime = array();
        $ans = '';

        shuffle( $birds );
        shuffle( $bname );

        $gettime[0] = microtime( true );

        foreach ( $birds as $key => $val ) {

            if ( false === strpos( $val, $bname[ $key ] ) ) {
                ++$ansnum[0];
            } else {
                ++$ansnum[1];
            }
        }

        $gettime[1] = microtime( true );
        $ans = $gettime[1] - $gettime[0];
        echo '<p>true : ' . $ansnum[1] . ' false : ' . $ansnum[0] . ' result : ' . sprintf( '%0.5f', $ans ) . '秒</p>';
    }

    echo '<p> str_contain 10,518回 x 5</p>';

    for ( $j = 1; $j < 6; ++$j ) {
        $ansnum = array( 0, 0 );
        $gettime = array();
        $ans = '';

        shuffle( $birds );
        shuffle( $bname );

        $gettime[0] = microtime( true );

        foreach ( $birds as $key => $val ) {

            if ( str_contains( $val, $bname[ $key ] ) ) {
                ++$ansnum[1];
            } else {
                ++$ansnum[0];
            }
        }

        $gettime[1] = microtime( true );
        $ans = $gettime[1] - $gettime[0];
        echo '<p>true : ' . $ansnum[1] . ' false : ' . $ansnum[0] . ' result : ' . sprintf( '%0.5f', $ans ) . '秒</p>';
    }

    // ちなみに限定的にしか使い道はないけれど、if を使わない手もある。速くなるだろうか?
    echo '<p> str_contain no-if 10,518回 x 5</p>';

    for ( $j = 1; $j < 6; ++$j ) {
        $ansnum = array( 0, 0 );
        $gettime = array();
        $ans = '';

        shuffle( $birds );
        shuffle( $bname );

        $gettime[0] = microtime( true );

        foreach ( $birds as $key => $val ) {

            $res = str_contains( $val, $bname[ $key ] );
            ++$ansnum[ $res ];

            // 以下のように一行でも書けるが、結果は上の二行書きの方が良いようだ。なぜかはわからない。
            // ++$ansnum[ str_contains( $val, $bname[ $key ] ) ];
        }

        $gettime[1] = microtime( true );
        $ans = $gettime[1] - $gettime[0];
        echo '<p>true : ' . $ansnum[1] . ' false : ' . $ansnum[0] . ' result : ' . sprintf( '%0.5f', $ans ) . '秒</p>';
    }

?>
PHP
CopyExpand

ちゃんと検索が機能しているか確認するために、結果も返すようにしてある。
テスト環境
Windows10 Pro 64bit
Apache2.4
php8.2

ベンチ結果

▶ Firefox Developer Edition 109.0b7 (64bit)

strpos str_contains str_contains no-if .00198 .00109 .00145 .00115 .00118 .00113 .00108 .00111 .00117 .00114 .00142 .00113 .00108 .00265 .00113

▶ Chrome canary 111.0.5509.0(64bit)

strpos str_contains str_contains no-if .00184 .00321 .00137 .00145 .00168 .00137 .00151 .00129 .00127 .00161 .00116 .00144 .00175 .00117 .00259

という結果となった。
Chrome においてはわずかながら str_contains の方が速いように見えるが、Firefox においてはあまり差はないようだ。しかし、不思議に思うのは php はサーバーで動くもののはず。なにゆえにブラウザによって違いが生ずるのだろうか。しかも Firefox の場合、Windows を起動して初めてそのブラウザを起動した後の一回目のテストは極端に遅い結果となる。二度目以降が別物のごとく速く一定した数値となるのは OPcache の効果なのだろうか。これが Chrome の場合だと、初回から二回目以降と同様の高速な結果が表示されることになる。そのあたりのブラウザによる違いというのもよくわからない。

結果をみると、str_containsstrpos にくらべ、すくなくとも遅くはないようなので、ただ単に文字列の存在を確認するだけの目的であれば、strpos には返り値の 0 の問題もあるし、str_contains を使うべきということになる。

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=173718

Sanbanse Funabashi
2011.01.01 sunrise

Top

スクロールさせるか画像をクリックすると元に戻ります。