Home  >  Article  >  Backend Development  >  Efficiency issues in parsing strtr function_PHP tutorial

Efficiency issues in parsing strtr function_PHP tutorial

WBOY
WBOYOriginal
2016-07-21 15:02:45838browse

Recently, I often need to match and replace strings. I usually used str_replace or preg_replace before. It is said that strtr is very efficient, so I compared it:

Copy code The code is as follows:

$i = 0;
$t = microtime(true);
for(;$i<1000;$i++)
{
$ str = strtr(md5($i), $p2);
}
var_dump(microtime(true)-$t); //0.085476875305176
$t = microtime(true);
for (;$i<2000;$i++)
{
$str = preg_replace($p, '', md5($i));
}
var_dump(microtime(true)-$ t); //0.09863805770874

The results show that strtr is about 15% more efficient than preg_replace.
I took advantage of the weekend to check the php source code of strtr:
Copy the code The code is as follows:

PHP_FUNCTION (strtr)
{
zval **str, **from, **to;
int ac = ZEND_NUM_ARGS();
//Parameter check (zend_get_parameters_ex function is defined in the zend_api.c file )
if (ac < 2 || ac > 3 || zend_get_parameters_ex(ac, &str, &from, &to) == FAILURE) {
WRONG_PARAM_COUNT;
}
// Parameter check
if (ac == 2 && Z_TYPE_PP(from) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument is not an array.");
RETURN_FAL SE;
}
convert_to_string_ex(str);
/* shortcut for empty string */
//Macro Z_STRLEN_PP is defined in zend_operators.h
if (Z_STRLEN_PP(str) == 0) {
RETURN_EMPTY_STRING() ;
}
if (ac == 2) {
php_strtr_array(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), HASH_OF(*from));
} else {
convert_to_string_ex (from);
_to_string_ex(to);
                                                                                                 Z_STRVAL_P(return_value),
                                                                                             
                                                                                                    MIN(Z_STRLEN_PP(from),
                                         

Let’s take a look at the php_strtr function first:



Copy the code
The code is as follows:

//trlen is the minimum length of the strings str_from and str_to
PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen)
{
int i;
unsigned char xlat[256]; //
if ((trlen < 1) || (len < 1)) {
return str;
}
//The subscript of xlat is equal to the value
for (i = 0; i < 256; xlat[i] = i, i++); Correspond. For example: from="ab",to="cd" will produce the correspondence 'a'=>'c', 'b'=>'d'.
                                                                   The efficiency of this function can be improved, because if the characters that need to be replaced only occupy a small part of the entire string, most of the assignment operations are actually meaningless. In this case, it feels like judging first and then assigning values. I feel it will be more efficient. I will test it when I have time)
for (i = 0; i < len; i++) {
str[i] = xlat[(unsigned char) str[i]];
}
                return str;

(Note: This operation outputs efcdeeefcd)


Look at php_strtr_array again:


Copy code
The code is as follows:

static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *hash)
{
zval **entry;
char *string_key;
uint string_key_len;
zval **trans;
zval ctmp;
ulong num_key;
int minlen = 128*1024;
int maxlen = 0, pos, len, found;
      char *key ;
HashPosition hpos;
smart_str result = {0};
HashTable tmp_hash;
//Copy the replacement array from hash to tmp_hash, and record the maximum and minimum length of the subscript string
zend_hash_init(&tmp_hash, 0, NULL, NULL, 0);
zend_hash_internal_pointer_reset_ex(hash, &hpos);
while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) {
switch (zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, 0, &hpos)) {
                                                                                   len = string_key_len-1;
                                                                                                                                                                                                                                                   through );
                                                                                                   zend_hash_add(&tmp_hash, string_key, string_key_len, entry, sizeof(zval*), NULL);                                                                      maxlen = len ;
                                                                                                                   minlen = len;
                                                     
                                                                                                                                   break; 🎜>                    case HASH_KEY_IS_LONG:
                                                                        Z_LVAL(ctmp) = num_key;
len = Z_STRLEN(ctmp);
                               zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len+1, entry, sizeof(zval*), NULL);
zval_dtor(&ctmp);
if (len > maxlen }
if (len & lt; minlen) {
minlen = len;
}
Break;
}
Zend_hash_Move_Forward_ex (have, & hpos); emalloc(maxlen+1);
pos = 0;
//Loop matching starting from the first character of the string, pos records the current search position
while (pos < slen) {
 ​                                                                                                                                                                                                                                                                                                        }
                              found = 0; ','ab'=>'f'), it will replace ab with f first instead of replacing a with e first.
                                                                                                                 Quite high
                   if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) {
                                                                       int tlen;
zval tmp;
if ( Z_TYPE_PP(trans) != IS_STRING) {
                                                                                                (andtmp); 🎜> tlen = Z_STRLEN (tmp);
                                                                                                                                  tlen = Z_STRLEN_PP(trans);                       
                                                                                                                                                                                                                                                                                                                                                                                                       If (Z_TYPE_PP(trans ) != IS_STRING) {
                                                                                                                                                                                       smart_str_appendc(&result, str[pos++ ]);
}
}
efree(key);
zend_hash_destroy(&tmp_hash);
smart_str_0(&result);
RETVAL_STRINGL(result.c, result.len, 0) ;
}






http://www.bkjia.com/PHPjc/327900.html

www.bkjia.com

true
http: //www.bkjia.com/PHPjc/327900.html
TechArticle

Recently, we often need to match and replace strings. In the past, we usually used str_replace or preg_replace. It is said that strtr is very efficient. , so compare it: Copy the code code as...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn