Образец текста:
$text = 'Administration\Controller\UserController::Save';
Задача – извлечь все до:
Опция 1:
list($module) = explode('::',$text);
Вариант 2:
$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: Был ли решение1 в 0.19701099395752 секунд. Был ли решение2 в 0.38502216339111 секунд.
Тест 2: Был ли раствор1 в 0.1990110874176 секунд. Было ли решение2 в 0,37402105331421 секунд.
Тест 3: Было ли решение1 в 0.19801092147827 секунд. Было ли решение2 в 0,37002205848694 секунд.
В моей системе:
~/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 могут иметь разные результаты. Вы должны проверить это самостоятельно и, конечно же, в конфигурации среды, идентичной вашей продукции.
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); } }
php_memnstr
будет вызывать 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.
Использование команды time
в Linux. Первый измерен в 0m0.024s
а второй – в 0m0.011s
.
Второй, кажется, быстрее. Я запускал его несколько раз, и результат (бар один раз) казался таким же.
EDIT: Как и было предложено, другой пользователь сказал, чтобы запустить его в петле 5000. Это завершено с теми же результатами.
эффективный? если вы имеете в виду по времени выполнения. затем запустите каждый из цикла (1000) и проверьте время выполнения.