PHP List + explode VS substr + strpos - which is more efficient?

Sample text:

$text = 'Administration\Controller\UserController::Save'; 

The task is to extract everything to:

Option 1:

 list($module) = explode('::',$text); 

Option 2:

 $module = substr($text, 0, strpos($text, '::'); 

Which option is more effective?

+7
source share
6 answers

I did a test and it seems the first solution is faster. Here is the code to test it:

 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"; 

Test 1: Was there a solution1 in 0.19701099395752 seconds. Was there a solution2 in 0.38502216339111 seconds.

Test 2: Was there a solution1 in 0.1990110874176 seconds. Was the solution2 in 0.37402105331421 seconds.

Test 3: Was there a solution1 in 0.19801092147827 seconds. Was the solution2 in 0.37002205848694 seconds.

+12
source

substr+strpos will be faster and take less processor time and will use less memeroy.

Find out the answer from php soruce code.

explode first:

 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 will call php_memnstr several times and add_next_index_stringl several times, which will work the result list .

Now 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); } 

It calls php_memnstr only once, and substr controls the input string in memery, returns sub one.

+6
source

In my system:

 ~/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 

I have the results:

 ~/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% 

Test code here: link . From time to time, the results are slightly different, but list+explode always faster than 15%.

Different PHP systems and versions may have different results. You must verify this yourself and, of course, in an environment configuration identical to your product.

+5
source

Using the time command on Linux. The first is measured at 0m0.024s , and the second at 0m0.011s .

The second seems to be faster. I ran it several times, and the result (bar once) seemed to be the same.

EDIT: as suggested, another user said to run it in the 5000 loop. This ended with the same results.

0
source

Tested: explode with a limit (solution3). Tested by: preg_match

note: 10,000 is not enough for me, so I run with 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"; } 

And the results:

 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. 

Solution 3 takes longer than solution1!

runs on cli, 100% CPU usage per thread

0
source

effective? if you mean by runtime. then run each of the loop (1000) and check the runtime.

-2
source

Source: https://habr.com/ru/post/953910/


All Articles