示例文本:
$text = 'Administration\Controller\UserController::Save';
任务-提取“::”之前的所有内容。
选项1:
list($module) = explode('::',$text);
方案二:
$module = substr($text, 0, strpos($text, '::');
哪个选项更有效率?
我运行了一个测试,似乎第一个解决方案更快。这是用于测试的代码:
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function solution1($text)
{
for($i = 0; $i < 10000; $i++)
list($module) = explode('::',$text);
}
function solution2($text)
{
for($i = 0; $i < 10000; $i++)
$module = substr($text, 0, strpos($text, '::'));
}
$text = 'Administration\Controller\UserController::Save';
$time_start = microtime_float();
solution1($text);
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "Did solution1 in $time seconds.\n";
$time_start = microtime_float();
solution2($text);
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "Did solution2 in $time seconds.\n";
测试 1: 在0.19701099395752秒内完成解决方案1。 在0.38502216339111秒内完成解决方案2。
测试 2: 在0.1990110874176秒内完成解决方案1。 在0.37402105331421秒内完成解决方案2。
测试 3: 在0.19801092147827秒内完成解决方案1。 在0.37002205848694秒内完成解决方案2。
解决方案1用时0.01142秒。
和解决方案2用时0.00609秒。
- jchooksubstr+strpos
将更快,占用较少的CPU时间和内存。
让我们从php源代码中找出答案。
首先使用explode
:
PHP_FUNCTION(explode)
{
// other codes
array_init(return_value);
if (str_len == 0) {
if (limit >= 0) {
add_next_index_stringl(return_value, "", sizeof("") - 1, 1);
}
return;
}
// other code
if (limit > 1) {
php_explode(&zdelim, &zstr, return_value, limit);
} else if (limit < 0) {
php_explode_negative_limit(&zdelim, &zstr, return_value, limit);
} else {
add_index_stringl(return_value, 0, str, str_len, 1);
}
}
PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
{
char *p1, *p2, *endp;
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
p1 = Z_STRVAL_P(str);
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
if (p2 == NULL) {
add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1);
} else {
do {
add_next_index_stringl(return_value, p1, p2 - p1, 1);
p1 = p2 + Z_STRLEN_P(delim);
} while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL &&
--limit > 1);
if (p1 <= endp)
add_next_index_stringl(return_value, p1, endp-p1, 1);
}
}
explode
函数会多次调用php_memnstr
和add_next_index_stringl
函数,这些函数会对结果列表
进行操作。
现在看看strpos
函数:
PHP_FUNCTION(strpos)
{
zval *needle;
char *haystack;
char *found = NULL;
char needle_char[2];
long offset = 0;
int haystack_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &haystack, &haystack_len, &needle, &offset) == FAILURE) {
return;
}
if (offset < 0 || offset > haystack_len) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");
RETURN_FALSE;
}
if (Z_TYPE_P(needle) == IS_STRING) {
if (!Z_STRLEN_P(needle)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty needle");
RETURN_FALSE;
}
found = php_memnstr(haystack + offset,
Z_STRVAL_P(needle),
Z_STRLEN_P(needle),
haystack + haystack_len);
} else {
if (php_needle_char(needle, needle_char TSRMLS_CC) != SUCCESS) {
RETURN_FALSE;
}
needle_char[1] = 0;
found = php_memnstr(haystack + offset,
needle_char,
1,
haystack + haystack_len);
}
if (found) {
RETURN_LONG(found - haystack);
} else {
RETURN_FALSE;
}
}
PHP_FUNCTION(substr)
{
// other code about postion
RETURN_STRINGL(str + f, l, 1);
}
它只调用了php_memnstr
一次,而substr
在内存中操作输入字符串,返回子字符串。
在我的系统上:
~/pb$ uname -a && php -v
Linux hostname 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1+deb7u1 x86_64 GNU/Linux
PHP 5.4.19-1~dotdeb.1 (cli) (built: Aug 27 2013 00:42:43)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
with XCache v3.0.3, Copyright (c) 2005-2013, by mOo
with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans
with XCache Cacher v3.0.3, Copyright (c) 2005-2013, by mOo
~/pb$ ./test ListVsSubstr
[============================================================>] 1000 u | 8134 u/s | Est: 0.0 s | Mem: 335.74 KB | Max: 357.96 KB
[============================================================>] 1000 u | 7808 u/s | Est: 0.0 s | Mem: 336.14 KB | Max: 357.96 KB
Test name Repeats Result Performance
list+explode 1000 0.044890 sec +0.00%
substr+strpos 1000 0.052825 sec -17.68%
这里有个测试代码:链接。
不同的系统和PHP版本可能会产生不同的结果。您需要自己检查,确保在与您的生产环境相同的环境配置下进行测试。但总体来说,list+explode
始终比其他方法快15%以上。
测试:带有限制的explode(解决方案3) 测试:preg_match
注意: 10000对我来说不够,所以我使用了10 000 000 x 3。
<?php
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function solution1($text)
{
for($i = 0; $i < 10000000; $i++)
list($module) = explode('::',$text);
}
function solution2($text)
{
for($i = 0; $i < 10000000; $i++)
$module = substr($text, 0, strpos($text, '::'));
}
function solution3($text)
{
for($i = 0; $i < 10000000; $i++)
list($module) = explode('::',$text, 2);
}
function solution4($text)
{
for($i = 0; $i < 10000000; $i++)
preg_match('/^(.*)::/', $text, $m) && $module = $m[1];
}
$text = 'Administration\Controller\UserController::Save';
for ($i=0; $i < 3; $i++) {
$time_start = microtime_float();
solution1($text);
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "Did solution1 in $time seconds.\n";
$time_start = microtime_float();
solution2($text);
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "Did solution2 in $time seconds.\n";
$time_start = microtime_float();
solution3($text);
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "Did solution3 in $time seconds.\n";
}
Did solution1 in 6.4486601352692 seconds.
Did solution2 in 9.4331159591675 seconds.
Did solution3 in 6.6791591644287 seconds.
Did solution4 in 9.3652379512787 seconds.
Did solution1 in 7.1072399616241 seconds.
Did solution2 in 10.755952835083 seconds.
Did solution3 in 7.5958750247955 seconds.
Did solution4 in 9.4377269744873 seconds.
Did solution1 in 7.4207429885864 seconds.
Did solution2 in 10.894104003906 seconds.
Did solution3 in 7.701789855957 seconds.
Did solution4 in 9.5081558227539 seconds.
$text ='The quick brown fox jumped over the lazy dog';
分割),则solution3
比solution1
快得多。 - Brandon在2.9455399513245秒内完成了解决方案1。 在0.7404088973999秒内完成了解决方案2。 在1.1065330505371秒内完成了解决方案3。
PHP 7.4 - Jack B在Linux上使用time
命令。第一个测量时间为0m0.024s
,第二个为0m0.011s
。
第二个似乎更快。我运行了多次,结果(除了一次)似乎都是相同的。
编辑:如建议所述,另一个用户建议将其循环5000次。结果与之前相同。
time php file.php
,第一个是关于 list/explode
的,第二个是 strpos
。 - andy高效?如果你指的是执行时间,那么就将每个程序在循环中运行多次(1000次),然后检查执行时间。
explode
,但大多数人会说substr
更有效。 - Flash Thunder