PHP list + explode VS substr+strpos-что более эффективно?
текст:
$text = 'AdministrationControllerUserController::Save';
задача - извлечь все до ::
Вариант 1:
list($module) = explode('::',$text);
Вариант 2:
$module = substr($text, 0, strpos($text, '::');
какой вариант более эффективен?
5 ответов
Я провел тест и кажется, что первое решение быстрее. Вот код для его тестирования:
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";
substr+strpos
будет быстрее и займет меньше времени процессора и использовать меньше memeroy.
Давайте узнаем ответ из кода PHP soruce.
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
несколько раз, которые будут работать the result list
.
теперь 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
управляет входной строкой в memery, возвращает sub one.
на моей системе:
~/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%
тестовый код здесь: ссылке.
Время от времени результаты немного отличаются, но list+explode
всегда быстрее, чем 15%.
различные системы и версии PHP могут иметь разные результаты. Вы должны проверить его самостоятельно и наверняка в конфигурации среды, идентичной вашей продукции.
С помощью time
команда в Linux. Первый измеряется в0m0.024s
и второй 0m0.011s
.
второй, кажется, быстрее. Я запускал его несколько раз, и результат (бар один раз) казался одинаковым.
EDIT: как было предложено, другой пользователь сказал, чтобы запустить его в цикле 5000. Это завершилось с теми же результатами.
эффективно ? если вы имеете в виду время исполнения. затем запустите каждый в цикле несколько (1000) раз и проверьте время выполнения.