"Performance for King" from PHP Source anatomy Array_keys and array_unique,arraykeys_php Tutorials

Source: Internet
Author: User

"Performance for the King" from the PHP source analysis Array_keys and Array_unique,arraykeys


Earlier in the [translate] faster way to implement PHP array de-weight This article discusses the use of Array_flip and then call the Array_keys function to replace the direct call array_unique function to achieve an array de-weight performance is good. Because the original text does not give the source code analysis and test results, causing confusion to the reader, say sorry. In order to solve the reader's doubts, the author promised to make up the source of the analysis, so spent some time to study the source of PHP, now this complements the detailed instructions.

Performance analysis

From the running performance analysis, look at the following test code:

$test=Array(); for($run= 0;$run<10000;$run++)$test[]=Rand(0,100);$time=Microtime(true);$out=Array_unique($test);$time=Microtime(true)-$time;Echo' Array Unique: '.$time." \ n ";$time=Microtime(true);$out=Array_keys(Array_flip($test));$time=Microtime(true)-$time;Echo' Keys Flip: '.$time." \ n ";$time=Microtime(true);$out=Array_flip(Array_flip($test));$time=Microtime(true)-$time;Echo' Flip flip: '.$time." \ n ";

The results of the operation are as follows:

As you can see, it takes 0.069s to use the Array_unique function, 0.00152s to use the Array_keys function after Array_flip, and 0.00146s to use the Array_flip function two times.

The test results show that it is faster to call the Array_keys function after using array_flip than the Array_unique function. So, what is the specific reason? Let's take a look at the bottom of PHP, how these two functions are implemented.

SOURCE Analysis

1 /*{{{proto array Array_keys (array input [, mixed search_value[, BOOL Strict]])2 Return just the keys from the input array, optionally only for the specified search_value*/3 php_function (Array_keys)4 {5     //variable definition6Zval *input,/*Input Array*/7*search_value = NULL,/*Value to search for*/8**entry,/*An entry in the input array*/9Res/*Result of comparison*/Ten*new_val;/*New Value*/ One     intAdd_key;/*Flag to indicate whether a key should be added*/ A     Char*string_key;/*String Key*/ -     UINTString_key_len; -     ULONGNum_key;/*Numeric Key*/ theZend_bool Strict =0;/*Do Strict comparison*/ - hashposition Pos; -     int(*is_equal_func) (Zval *, Zval *, Zval * tsrmls_dc) =is_equal_function; -  +     //Program parsing Parameters -     if(Zend_parse_parameters (Zend_num_args () TSRMLS_CC,"A|ZB", &input, &search_value, &strict) = =FAILURE) { +         return; A     } at  -     //If Strict is true, the Is_equal_func is set to Is_identical_function, which is the congruent comparison -     if(Strict) { -Is_equal_func =is_identical_function; -     } -  in     /*the size of the returned array based on Search_vale initialization*/ -     if(Search_value! =NULL) { to Array_init (return_value); +}Else { - array_init_size (Return_value, zend_hash_num_elements (z_arrval_p (input))); the     } *Add_key =1; $ Panax Notoginseng     /*iterate through the input array parameters, and then add the key values to the returned array*/ -ZEND_HASH_INTERNAL_POINTER_RESET_EX (z_arrval_p (input), &pos);//Reset pointer the     //Iterating through an array +      while(ZEND_HASH_GET_CURRENT_DATA_EX (z_arrval_p (input), (void* *) &entry, &pos) = =SUCCESS) { A         //If the search_value is not empty the         if(Search_value! =NULL) { +             //determines whether the search_value is the same as the current value and saves the comparison result to the Add_key variable -Is_equal_func (&res, Search_value, *entry tsrmls_cc); $Add_key = Zval_is_true (&res); $         } -  -         if(add_key) { the             //Create a zval structure body - Make_std_zval (new_val);Wuyi  the             //inserts a value into return_value based on whether the key value is a string or an integer number -             Switch(ZEND_HASH_GET_CURRENT_KEY_EX (z_arrval_p (input), &string_key, &string_key_len, &num_key,1, &POS)) { Wu                  Casehash_key_is_string: -Zval_stringl (New_val, String_key, String_key_len-1,0); About                     //This function is responsible for inserting the value into the Return_value, and if the key value already exists, update the corresponding value with the new value, otherwise insert directly $Zend_hash_next_index_insert (Z_arrval_p (Return_value), &new_val,sizeof(Zval *), NULL); -                      Break; -  -                  CaseHash_key_is_long: AZ_type_p (New_val) =Is_long; +Z_lval_p (New_val) =Num_key; theZend_hash_next_index_insert (Z_arrval_p (Return_value), &new_val,sizeof(Zval *), NULL); -                      Break; $             } the         } the  the         //move to the next theZEND_HASH_MOVE_FORWARD_EX (z_arrval_p (input), &POS); -     } in } the /* }}} */

The above is the Array_keys function of the underlying source. For the convenience of understanding, the author added some Chinese comments. If you need to see the original code, you can click View. The function is to create a new temporary array, then copy the key-value pairs back into the new array, and replace them with the new values if duplicate key values appear during the copy process. The main step of this function is to invoke the Zend_hash_next_index_insert function in rows 57 and 63. The function inserts the element into the array, and if a duplicate value is present, the value pointed to by the original key value is updated with the new value, otherwise it is directly inserted and the time complexity is O (n).

1 /*{{{proto array array_flip (array input)2 Return array with key <-> value flipped*/3 php_function (Array_flip)4 {5     //Defining Variables6Zval *array, **entry, *data;7     Char*String_key;8     UINTStr_key_len;9     ULONGNum_key;Ten hashposition Pos; One  A     //Parsing Array Parameters -     if(Zend_parse_parameters (Zend_num_args () TSRMLS_CC,"a", &array) = =FAILURE) { -         return; the     } -  -     //Initialize the returned array - array_init_size (Return_value, zend_hash_num_elements (z_arrval_p (array))); +  -     //Reset pointer +ZEND_HASH_INTERNAL_POINTER_RESET_EX (z_arrval_p (array), &POS); A     //iterate through each element and perform key <-> value Exchange operations at      while(ZEND_HASH_GET_CURRENT_DATA_EX (z_arrval_p (array), (void* *) &entry, &pos) = =SUCCESS) { -         //Initialize a struct - make_std_zval (data); -         //assigns the value of the original array to the key of the new array -         Switch(ZEND_HASH_GET_CURRENT_KEY_EX (z_arrval_p (array), &string_key, &str_key_len, &num_key,1, &POS)) { -              Casehash_key_is_string: inZval_stringl (data, String_key, Str_key_len-1,0); -                  Break; to              CaseHash_key_is_long: +Z_type_p (data) =Is_long; -Z_lval_p (data) =Num_key; the                  Break; *         } $ Panax Notoginseng         //assigns the key of the original array to the value of the new array, overwriting the old value with the new value if there are duplicates -         if(Z_TYPE_PP (entry) = =Is_long) { theZend_hash_index_update (Z_arrval_p (Return_value), z_lval_pp (entry), &data,sizeof(data), NULL); +}Else if(Z_TYPE_PP (entry) = =is_string) { AZend_symtable_update (Z_arrval_p (Return_value), z_strval_pp (entry), Z_STRLEN_PP (entry) +1, &data,sizeof(data), NULL); the}Else { +Zval_ptr_dtor (&data);/*Would free also zval structure*/ -Php_error_docref (NULL tsrmls_cc, e_warning,"Can only Flip STRING and INTEGER values!"); $         } $  -         //Next -ZEND_HASH_MOVE_FORWARD_EX (z_arrval_p (array), &POS); the     } - }Wuyi /* }}} */

Above is the source code of the Array_flip function. Click the link to view the original code. The main thing this function does is create a new array and iterate over the original array. Start by assigning the value of the original array to the key of the new array at line 26, and then start assigning the key of the original array to the value of the new array at 37 rows, overwriting the old value with the new value if there are duplicates. The time complexity of the entire function is also O (n). Therefore, the time complexity of using Array_keys after using Array_flip is O (n).

Next, let's look at the source code of the Array_unique function. Click the link to view the original code.

1 /*{{{{proto array array_unique (array input [, int sort_flags])2 removes duplicate values from array*/3 php_function (Array_unique)4 {5     //Defining Variables6Zval *array, *tmp;7Bucket *p;8     structBucketindex {9Bucket *b;TenUnsignedinti; One     }; A     structBucketindex *artmp, *cmpdata, *lastkept; -Unsignedinti; -     LongSort_type =php_sort_string; the  -     //parsing Parameters -     if(Zend_parse_parameters (Zend_num_args () TSRMLS_CC,"a|l", &array, &sort_type) = =FAILURE) { -         return; +     } -  +     //Setting the comparison function A Php_set_compare_func (Sort_type tsrmls_cc); at  -     //Initialize the returned array - array_init_size (Return_value, zend_hash_num_elements (z_arrval_p (array))); -     //copy a value to a new array -Zend_hash_copy (Z_arrval_p (Return_value), z_arrval_p (array), (copy_ctor_func_t) Zval_add_ref, (void*) &tmp,sizeof(zval*)); -  in     if(z_arrval_p (array)->nnumofelements <=1) {/*don't do anything.*/ -         return; to     } +  -     /*creates an array and sorts according to the pointer of Target_hash buckets*/ theArtmp = (structBucketindex *) Pemalloc ((z_arrval_p (array)->nnumofelements +1) *sizeof(structBucketindex), z_arrval_p (array),persistent); *     if(!artmp) { $ Zval_dtor (return_value);Panax Notoginseng Return_false; -     } the      for(i =0, p = z_arrval_p (array)->plisthead; P i++, p = p->Plistnext) { +ARTMP[I].B =p; AARTMP[I].I =i; the     } +ARTMP[I].B =NULL; -     //Sort $Zend_qsort ((void*) artmp, I,sizeof(structbucketindex), Php_array_data_compare tsrmls_cc); $  -     /*iterate through the sorted array, then delete the duplicate elements*/ -Lastkept =artmp; the      for(Cmpdata = artmp +1; cmpdata->b; cmpdata++) { -         if(Php_array_data_compare (lastkept, Cmpdata tsrmls_cc)) {WuyiLastkept =Cmpdata; the}Else { -             if(Lastkept->i > cmpdata->i) { Wup = lastkept->b; -Lastkept =Cmpdata; About}Else { $p = cmpdata->b; -             } -             if(P->nkeylength = =0) { -Zend_hash_index_del (Z_arrval_p (return_value), p->h); A}Else { +                 if(Z_arrval_p (return_value) = = &EG (symbol_table)) { theZend_delete_global_variable (P->arkey, P->nkeylength-1tsrmls_cc); -}Else { $Zend_hash_quick_del (Z_arrval_p (Return_value), P->arkey, P->nkeylength, p->h); the                 } the             } the         } the     } -Pefree (artmp, z_arrval_p (array)persistent); in } the /* }}} */

As you can see, this function initializes a new array, then copies the values to the new array, and then calls the sort function on the 45 rows to order the array, sorting the algorithm is the Block tree sorting algorithm of the Zend engine. Then iterate through the sorted array and delete the duplicate elements. The most expensive place for the entire function is on the call sort function, and the time complexity of the N*LOGN is O (-), so the time complexity of the function is O (N*LOGN).

Conclusion

Because the Array_unique bottom calls the fast algorithm, increases the function running time overhead, causes the whole function to run slower. This is why Array_keys is faster than the Array_unique function.

Original article, writing Limited, Caishuxueqian, if there is not in the text, million hope to inform.

If this article is helpful to you, please click on the recommendation, write the article is not easy.

http://www.bkjia.com/PHPjc/1102855.html www.bkjia.com true http://www.bkjia.com/PHPjc/1102855.html techarticle "Performance for the King" from the PHP source analysis Array_keys and Array_unique,arraykeys before the [translate] faster way to implement PHP array to re-weight this article discusses the use of Array_flip after the call Arra ...

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.