PHP list+explode VS substr+strpos - what is more efficient?

后端 未结 6 1709
迷失自我
迷失自我 2021-01-04 22:24

Sample text:

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

Task - extract everything before ::

Option 1:

         


        
6条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-04 22:34

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

    Let's 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 multiple times and add_next_index_stringl multiple times which will operate 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 one time, and substr operates the input string in memery, return the sub one.

提交回复
热议问题