php 7 mb_(多字节)函数比5.3(仅限windows)更慢约60%

Mir*_*ror 8 php performance php-7 php-7.1

我的应用程序广泛使用mb_字符串函数,并切换到PHP 7导致整体较慢的应用程序.我将问题跟踪到mb_字符串函数.以下是基准代码和结果:

$time = microtime();
$time = explode(' ', $time);
$start = $time[1] + $time[0];
$startms = $time[0];
    for ($i=0; $i<100000; $i++) {
        $a = mb_strlen("fdsfdssdfoifjosdifjosdifjosdij:?", "UTF-8");
    }
$time = microtime();
$time = explode(' ', $time);
$finish = $time[1] + $time[0];
$finishms = $time[0];
$total_time = round(($finish - $start), 4);
echo "mb_strlen: " . $total_time*1000 ." milliseconds<br/>";

$time = microtime();
$time = explode(' ', $time);
$start = $time[1] + $time[0];
$startms = $time[0];
    for ($i=0; $i<100000; $i++) {
        $a = mb_stripos("fdsfdssdfoifjosdifjosdifjosdij:?", "?", 0, "UTF-8");
    }
$time = microtime();
$time = explode(' ', $time);
$finish = $time[1] + $time[0];
$finishms = $time[0];
$total_time = round(($finish - $start), 4);
echo "mb_stripos: " . $total_time*1000 ." milliseconds<br/>";


$time = microtime();
$time = explode(' ', $time);
$start = $time[1] + $time[0];
$startms = $time[0];
    for ($i=0; $i<100000; $i++) {
        $a = mb_substr("fdsfdssdfoifjosdifjosdifjosdij:?", $i, 1, "UTF-8");
    }
$time = microtime();
$time = explode(' ', $time);
$finish = $time[1] + $time[0];
$finishms = $time[0];
$total_time = round(($finish - $start), 4);
echo "mb_substr: " . $total_time*1000 ." milliseconds<br/>";
Run Code Online (Sandbox Code Playgroud)

该平台是Windows 7 64位,IIS 7.5:

php 5.3.28
mb_strlen: 250 milliseconds
mb_stripos: 3078.1 milliseconds
mb_substr: 281.3 milliseconds

php 7.1.1
mb_strlen: 406.3 milliseconds
mb_stripos: 4796.9 milliseconds
mb_substr: 421.9 milliseconds
Run Code Online (Sandbox Code Playgroud)

我不知道我的设置是错还是什么,但多字节功能应该慢一点似乎不可思议.关于为什么以及如何解决这个问题的任何想法?先感谢您.

编辑:正如apokryfos的评论所暗示的,这可能是Windows唯一的问题.

Rei*_*Rei 4

我可以确认您的结果在 Windows 7 上是可以重现的。\n经过一些实验,我找到了一个快速解决方案,IMO 甚至不应该产生影响。

\n\n

从mb_strlen()可以看出,如果省略编码参数,\n它将使用内部编码。\n这也适用于您使用的其他函数。

\n\n
mixed mb_strlen ( string $str [, string $encoding = mb_internal_encoding() ] )\n
Run Code Online (Sandbox Code Playgroud)\n\n

我发现奇怪的是,如果您通过调用将内部编码设置为 UTF-8mb_internal_encoding("UTF-8")并省略编码参数,\n函数会变得更快。

\n\n

PHP 5.5 结果:

\n\n
5.5.12\n\nwith encoding parameter:\n- mb_strlen: 172 ms, result: 5\n- mb_substr: 218 ms, result: \xe3\x81\x86\n- mb_strpos: 218 ms, result: 3\n- mb_stripos: 1,669 ms, result: 3\n- mb_strrpos: 234 ms, result: 3\n- mb_strripos: 1,685 ms, result: 3\n\nwith internal encoding:\n- mb_strlen: 47 ms, result: 5\n- mb_substr: 78 ms, result: \xe3\x81\x86\n- mb_strpos: 62 ms, result: 3\n- mb_stripos: 1,669 ms, result: 3\n- mb_strrpos: 94 ms, result: 3\n- mb_strripos: 1,669 ms, result: 3\n
Run Code Online (Sandbox Code Playgroud)\n\n

PHP 7.0 结果:

\n\n
7.0.12\n\nwith encoding parameter:\n- mb_strlen: 640 ms, result: 5\n- mb_substr: 702 ms, result: \xe3\x81\x86\n- mb_strpos: 686 ms, result: 3\n- mb_stripos: 7,067 ms, result: 3\n- mb_strrpos: 749 ms, result: 3\n- mb_strripos: 7,130 ms, result: 3\n\nwith internal encoding:\n- mb_strlen: 31 ms, result: 5\n- mb_substr: 31 ms, result: \xe3\x81\x86\n- mb_strpos: 47 ms, result: 3\n- mb_stripos: 7,270 ms, result: 3\n- mb_strrpos: 62 ms, result: 3\n- mb_strripos: 7,116 ms, result: 3\n
Run Code Online (Sandbox Code Playgroud)\n\n

不幸的是,这个快速解决方案并不完美,mb_stripos()并且mb_strripos()似乎没有受到影响。\n它们仍然很慢。

\n\n

这是代码(缩短):

\n\n
echo PHP_VERSION."\\n";\necho "\\nwith encoding parameter:\\n";\n\n$t = microtime(true)*1000;\nfor($i=0; $i<100000; $i++){\n    $n = mb_strlen("\xe3\x81\x82\xe3\x81\x88\xe3\x81\x84\xe3\x81\x8a\xe3\x81\x86","UTF-8");\n}\n$t = microtime(true)*1000-$t;\necho "- mb_strlen: ".number_format($t)." ms, result: {$n}\\n";\n\n$t = microtime(true)*1000;\nfor($i=0; $i<100000; $i++){\n    $n = mb_substr("\xe3\x81\x82\xe3\x81\x88\xe3\x81\x84\xe3\x81\x8a\xe3\x81\x86",-1,1,"UTF-8");\n}\n$t = microtime(true)*1000-$t;\necho "- mb_substr: ".number_format($t)." ms, result: {$n}\\n";\n\n//set internal encoding\n//and omit encoding parameter\n\nmb_internal_encoding("UTF-8");\necho "\\nwith internal encoding:\\n";\n\n$t = microtime(true)*1000;\nfor($i=0; $i<100000; $i++){\n    $n = mb_strlen("\xe3\x81\x82\xe3\x81\x88\xe3\x81\x84\xe3\x81\x8a\xe3\x81\x86");\n}\n$t = microtime(true)*1000-$t;\necho "- mb_strlen: ".number_format($t)." ms, result: {$n}\\n";\n\n$t = microtime(true)*1000;\nfor($i=0; $i<100000; $i++){\n    $n = mb_substr("\xe3\x81\x82\xe3\x81\x88\xe3\x81\x84\xe3\x81\x8a\xe3\x81\x86",-1,1);\n}\n$t = microtime(true)*1000-$t;\necho "- mb_substr: ".number_format($t)." ms, result: {$n}\\n";\n
Run Code Online (Sandbox Code Playgroud)\n