我的应用程序广泛使用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:ά","α",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,4); echo "mb_substr: " . $total_time*1000 ." milliseconds<br/>";
该平台是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
我不知道我的设置是错还是什么,但似乎不可思议的是多字节功能应该更慢.关于为什么以及如何解决这个问题的任何想法?先感谢您.
编辑:正如apokryfos的评论所暗示的,这可能是Windows唯一的问题.
我可以确认您的结果在Windows 7上是可重现的.
经过一些实验,我找到了一个快速的解决方案,即IMO甚至不应该产生影响.
经过一些实验,我找到了一个快速的解决方案,即IMO甚至不应该产生影响.
从mb_strlen()功能签名可以看出,
如果省略encoding参数,它将使用内部编码.
这也适用于您使用的其他功能.
mixed mb_strlen ( string $str [,string $encoding = mb_internal_encoding() ] )
我发现奇怪的是,如果你通过调用mb_internal_encoding(“UTF-8”)将内部编码设置为UTF-8并省略编码参数,
功能变得更快.
PHP 5.5结果:
5.5.12 with encoding parameter: - mb_strlen: 172 ms,result: 5 - mb_substr: 218 ms,result: う - mb_strpos: 218 ms,result: 3 - mb_stripos: 1,669 ms,result: 3 - mb_strrpos: 234 ms,result: 3 - mb_strripos: 1,685 ms,result: 3 with internal encoding: - mb_strlen: 47 ms,result: 5 - mb_substr: 78 ms,result: う - mb_strpos: 62 ms,result: 3 - mb_strrpos: 94 ms,result: 3
PHP 7.0结果:
7.0.12 with encoding parameter: - mb_strlen: 640 ms,result: 5 - mb_substr: 702 ms,result: う - mb_strpos: 686 ms,result: 3 - mb_stripos: 7,067 ms,result: 3 - mb_strrpos: 749 ms,result: 3 - mb_strripos: 7,130 ms,result: 3 with internal encoding: - mb_strlen: 31 ms,result: 5 - mb_substr: 31 ms,result: う - mb_strpos: 47 ms,270 ms,result: 3 - mb_strrpos: 62 ms,116 ms,result: 3
不幸的是,这种快速解决方案并不完美,因为mb_stripos()和mb_strripos()似乎没有受到影响.
他们仍然很慢.
这是代码(缩写):
echo PHP_VERSION."\n"; echo "\nwith encoding parameter:\n"; $t = microtime(true)*1000; for($i=0; $i<100000; $i++){ $n = mb_strlen("あえいおう","UTF-8"); } $t = microtime(true)*1000-$t; echo "- mb_strlen: ".number_format($t)." ms,result: {$n}\n"; $t = microtime(true)*1000; for($i=0; $i<100000; $i++){ $n = mb_substr("あえいおう",-1,"UTF-8"); } $t = microtime(true)*1000-$t; echo "- mb_substr: ".number_format($t)." ms,result: {$n}\n"; //set internal encoding //and omit encoding parameter mb_internal_encoding("UTF-8"); echo "\nwith internal encoding:\n"; $t = microtime(true)*1000; for($i=0; $i<100000; $i++){ $n = mb_strlen("あえいおう"); } $t = microtime(true)*1000-$t; echo "- mb_strlen: ".number_format($t)." ms,1); } $t = microtime(true)*1000-$t; echo "- mb_substr: ".number_format($t)." ms,result: {$n}\n";