在 PHP8 的更新中对字符串操作新增了三个函数,这三个函数分别是str_containsstr_starts_withstr_ends_with, 在PHP8以前这三个函数在主流框架如Laravel、Yii中都提供。一般来说PHP内置的函数都会比我们用PHP写的要快不少,但是相比框架提供的这些函数到底性能提升了多少呢?

因此我写了个小程序进行了验证实验,我做实验的机器是一台iMac,机器配置如下

MacOS Big Sur
Version 11.3.1

iMac(Retina 5K, 27-inch, 2017)
Processor 3.4GHz Quad-Core Intel Core i5
Memory 32 GB 2400 MHz DDR4
Startup Disk Macintosh HD
Graphics Radeon Pro 570 4GB

PHP 版本如下

PHP 8.0.5 (cli) (built: Apr 29 2021 16:01:35) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.5, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.5, Copyright (c), by Zend Technologies

实验程序代码:


Artisan::command('test0', function () {
    $count = 1000000;
    $laravel_time = microtime(true) - LARAVEL_START;
    echo 'Laravel run time is ' . $laravel_time . PHP_EOL . PHP_EOL;

    $arr = [];
    for ($j = 0; $j < 5; $j ++ ) {
        $start = microtime(true);
        for ($i = 0; $i < $count; $i++) \Illuminate\Support\Str::contains('abc', 'a');
        $end = microtime(true);

        $laravel_str_time = $end - $start;

        echo 'Str::contains run is ' . $laravel_str_time . PHP_EOL;

        $start = microtime(true);
        for ($i = 0; $i < $count; $i++) str_contains('abc', 'a');
        $end = microtime(true);

        $php8_str_time = $end - $start;

        echo 'PHP8 str_contains run is ' . $php8_str_time . PHP_EOL . PHP_EOL;

        $arr[] = number_format($php8_str_time / $laravel_str_time, 4);
    }

    var_dump($arr);
    echo array_sum($arr) / count($arr);
});

程序输出:

php artisan test0                                
Laravel run time is 0.10241389274597

Str::contains run is 0.11590790748596
PHP8 str_contains run is 0.025718927383423

Str::contains run is 0.11841297149658
PHP8 str_contains run is 0.024212121963501

Str::contains run is 0.11694502830505
PHP8 str_contains run is 0.025036096572876

Str::contains run is 0.11578488349915
PHP8 str_contains run is 0.025848865509033

Str::contains run is 0.11652398109436
PHP8 str_contains run is 0.026134014129639

array(5) {
  [0]=>
  string(6) "0.2219"
  [1]=>
  string(6) "0.2045"
  [2]=>
  string(6) "0.2141"
  [3]=>
  string(6) "0.2232"
  [4]=>
  string(6) "0.2243"
}
0.2176% 

用同样的程序,修改调用的方法分别对 str_starts_with 和 str_ends_with 进行实验,输出如下:

Laravel run time is 0.097244024276733

Str::startsWith run is 0.13129806518555
PHP8 str_starts_with run is 0.023024082183838

Str::startsWith run is 0.13406491279602
PHP8 str_starts_with run is 0.024108171463013

Str::startsWith run is 0.13589406013489
PHP8 str_starts_with run is 0.025053024291992

Str::startsWith run is 0.13407921791077
PHP8 str_starts_with run is 0.024497985839844

Str::startsWith run is 0.13846492767334
PHP8 str_starts_with run is 0.024585962295532

array(5) {
  [0]=>
  string(6) "0.1754"
  [1]=>
  string(6) "0.1798"
  [2]=>
  string(6) "0.1844"
  [3]=>
  string(6) "0.1827"
  [4]=>
  string(6) "0.1776"
}
0.17998%                        
Laravel run time is 0.094044923782349

Str::endsWith run is 0.12809109687805
PHP8 str_ends_with run is 0.023317098617554

Str::endsWith run is 0.12816786766052
PHP8 str_ends_with run is 0.023905038833618

Str::endsWith run is 0.12953305244446
PHP8 str_ends_with run is 0.024739027023315

Str::endsWith run is 0.13504600524902
PHP8 str_ends_with run is 0.025351047515869

Str::endsWith run is 0.13313508033752
PHP8 str_ends_with run is 0.025480985641479

array(5) {
  [0]=>
  string(6) "0.1820"
  [1]=>
  string(6) "0.1865"
  [2]=>
  string(6) "0.1910"
  [3]=>
  string(6) "0.1877"
  [4]=>
  string(6) "0.1914"
}
0.18772% 

可以看出性能相比于应用框架所提供的提升在 18%-20% 这个范围,另一点是 str_contains 可以很好的替代 strpos 和 strstr 这两个PHP函数,而不需要再进行 !== 或 === 的判断。