[Performance is King] array_keys, array_unique, and arraykeys_PHP tutorials from the PHP source code

Source: Internet
Author: User
[Performance is King] array_keys, array_unique, and arraykeys are analyzed from the PHP source code. [Performance is King] array_keys and array_unique are analyzed from the PHP source code, arraykeys previously discussed how to achieve PHP array de-duplication in [Translation]. array_flip is used before calling arra [performance is king]. array_keys, array_unique, and arraykeys are analyzed from the PHP source code.

Previously, the article discussed how to implement PHP array de-duplication in a faster way in [Translation]. after array_flip is used, it is better to call the array_keys function to replace the array_unique function to implement array de-duplication. The source code analysis and testing results are not provided in the original text, which may lead to confusion for readers. sorry. In order to solve the reader's doubts, I promised to add the source code analysis, so I spent some time studying the PHP source code. now I will add a detailed description here.

Performance analysis

Analyze the running performance to see 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 running result is as follows:

As you can see, the array_unique function requires 0.069 s, the array_flip function requires 0.00152 s, and the array_keys function requires 0.00146 s. The array_flip function requires s.

The test results show that calling the array_keys function after array_flip is faster than the array_unique function. So what are the specific reasons? Let's see how these two functions are implemented at the bottom layer of PHP.

Source Code 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 definition 6 zval * input,/* Input array */7 * search_value = NULL, /* Value to search for */8 ** entry,/* An entry in the input array */9 res,/* Result of comparison */10 * new_val; /* New va Lue */11 int add_key;/* Flag to indicate whether a key shocould be added */12 char * string_key;/* String key */13 uint string_key_len; 14 ulong num_key; /* Numeric key */15 zend_bool strict = 0;/* do strict comparison */16 HashPosition pos; 17 int (* is_0000_func) (zval *, zval *, zval * TSRMLS_DC) = is_equal_function; 18 19 // The program parses the parameter 20 if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "a | zb", & Indium Ut, & search_value, & strict) = FAILURE) {21 return; 22} 23 24 // if strict is true, set is_assist_func to is_identical_function, that is, compare 25 if (strict) {26 is_effec_func = is_identical_function; 27} 28 29/* initialize the returned array size based on search_vale */30 if (search_value! = NULL) {31 array_init (return_value); 32} else {33 array_init_size (return_value, zend_hash_num_elements (Z_ARRVAL_P (input); 34} 35 add_key = 1; 36 37/* traverse the input array parameters and add the key value to the returned array */38 zend_hash_internal_pointer_reset_ex (Z_ARRVAL_P (input), & pos ); // reset pointer 39 // cyclically traverse array 40 while (zend_hash_get_current_data_ex (Z_ARRVAL_P (input), (void **) & entry, & pos) = SUCCESS) {41 // if search_value is not null 42 if (search_value! = NULL) {43 // Determine whether search_value is the same as the current value, and save the comparison result to the add_key variable 44 is_1__func (& res, search_value, * entry TSRMLS_CC ); 45 add_key = zval_is_true (& res); 46} 47 48 if (add_key) {49 // Create a zval struct 50 MAKE_STD_ZVAL (new_val ); 51 52 // Insert values into return_value based on whether the key value is a string or an integer. 53 switch (zend_hash_get_current_key_ex (Z_ARRVAL_P (input), & string_key, & string_key_len, & num_key, & pos) {54 case HASH_KEY_IS_STRING: 55 ZVAL_STRINGL (new_val, string_key, string_key_len-1, 0); 56 // This function inserts the value into return_value, if the key value already exists, use the new value to update the corresponding value. otherwise, insert 57 zend_hash_next_index_insert (Z_ARRVAL_P (return_value), & new_val, sizeof (zval *), NULL) directly ); 58 break; 59 60 case HASH_KEY_IS_LONG: 61 Z_TYPE_P (new_val) = IS_LONG; 62 Z_LVAL_P (new_val) = num_key; 63 values (Z_ARRVAL_P (return_value), & new_val, sizeof (zval *), NULL); 64 break; 65} 66} 67 68 // move to the next 69 zend_hash_move_forward_ex (Z_ARRVAL_P (input), & pos ); 70} 71} 72 /*}}}*/

The above is the underlying source code of the array_keys function. For ease of understanding, I have added some Chinese notes. To view the original code, click here. This function creates a temporary array and copies key-value pairs to the new array. if duplicate key-value pairs appear during the replication process, replace them with new values. The main steps of this function are to call the zend_hash_next_index_insert function in rows 57 and 63. This function inserts elements into the array. if repeated values exist, the new value is used to update the value pointed to by the original key value. Otherwise, the new value is inserted directly. 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 // define the variable 6 zval * array, ** entry, * data; 7 char * string_key; 8 uint str_key_len; 9 ulong num_key; 10 HashPosition pos; 11 12 // Parse the array parameter 13 if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "a", & array) = FAILURE) {14 return; 15} 16 17 // The Returned array 18 array_init_size (return_value, zen D_hash_num_elements (Z_ARRVAL_P (array); 19 20 // reset pointer 21 zend_hash_internal_pointer_reset_ex (Z_ARRVAL_P (array), & pos); 22 // traverse each element, perform the <-> value exchange operation 23 while (zend_hash_get_current_data_ex (Z_ARRVAL_P (array), (void **) & entry, & pos) = SUCCESS) {24 // initialize a struct 25 MAKE_STD_ZVAL (data); 26 // assign the value of the original array to the 27 switch (zend_hash_get_current_key_ex (Z_ARRVAL_P (array), & string_key, & str_key_len, & num_key, 1, & pos )) {28 case HASH_KEY_IS_STRING: 29 ZVAL_STRINGL (data, string_key, str_key_len-1, 0); 30 break; 31 case when: 32 Z_TYPE_P (data) = IS_LONG; 33 Z_LVAL_P (data) = num_key; 34 break; 35} 36 37 // assign the key of the original array to the value of the new array. if there is a duplicate, the old value 38 if (Z_TYPE_PP (entry) = IS_LONG) {39 zend_hash_index_update (Z_ARRVAL_P (return_value), Z_LVAL_PP (entry), & data, sizeof (data ), NULL); 40} else if (Z_TYPE_PP (entry) = IS_STRI NG) {41 zend_symtable_update (Z_ARRVAL_P (return_value), Z_STRVAL_PP (entry), Z_STRLEN_PP (entry) + 1, & data, sizeof (data), NULL ); 42} else {43 zval_ptr_dtor (& data);/* will free also zval structure */44 php_error_docref (NULL TSRMLS_CC, E_WARNING, "Can flionly p STRING and INTEGER values! "); 45} 46 47 // the next 48 zend_hash_move_forward_ex (Z_ARRVAL_P (array), & pos); 49} 50} 51 /*}}}*/

The above is the source code of the array_flip function. Click the link to view the original code. The main task of this function is to create a new array and traverse the original array. At the beginning of 26 rows, assign the value of the original array to the key of the new array, and then assign the key of the original array to the value of the new array at the beginning of 37 rows. if there are repeated values, overwrite the old value with the new value. The time complexity of the entire function is O (n ). Therefore, the time complexity of using array_keys after 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 // define the variable 6 zval * array, * tmp; 7 Bucket * p; 8 struct bucketindex {9 Bucket * B; 10 unsigned int I; 11 }; 12 struct bucketindex * arTmp, * cmpdata, * lastkept; 13 unsigned int I; 14 long sort_type = PHP_SORT_STRING; 15 16 // resolution parameter 17 if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "a | l", & array, & sort_type) = FAILURE) {18 return; 19} 20 21 // Set the comparison function 22 php_set_compare_func (sort_type TSRMLS_CC ); 23 24 // array 25 returned for initialization array_init_size (return_value, values (Z_ARRVAL_P (array); 26 // Copy the value to the new array 27 zend_hash_copy (Z_ARRVAL_P (return_value ), z_ARRVAL_P (array), (copy_ctor_func_t) zval_add_ref, (void *) & tmp, sizeof (zval *); 28 29 if (Z_ARRVAL_P (array)-> nNumOfElemen Ts <= 1) {/* do nothing */30 return; 31} 32 33/* create an array based on the target_hash buckets pointer and sort the array */34 arTmp = (struct bucketindex *) pemalloc (Z_ARRVAL_P (array)-> nNumOfElements + 1) * sizeof (struct bucketindex), Z_ARRVAL_P (array)-> persistent); 35 if (! ArTmp) {36 zval_dtor (return_value); 37 RETURN_FALSE; 38} 39 for (I = 0, p = Z_ARRVAL_P (array)-> pListHead; p; I ++, p = p-> pListNext) {40 arTmp [I]. B = p; 41 arTmp [I]. I = I; 42} 43 arTmp [I]. B = NULL; 44 // sort 45 zend_qsort (void *) arTmp, I, sizeof (struct bucketindex), php_array_data_compare TSRMLS_CC); 46 47/* traverse the sorted array, then delete the repeated elements */48 lastkept = arTmp; 49 for (cmpdata = arTmp + 1; cmpdata-> B; cmpdata ++) {50 if (php_array_data_compare (lastkept, cmpdata TSRMLS_CC) {51 lastkept = cmpdata; 52} else {53 if (lastkept-> I> cmpdata-> I) {54 p = lastkept-> B; 55 lastkept = cmpdata; 56} else {57 p = cmpdata-> B; 58} 59 if (p-> nKeyLength = 0) {60 zend_hash_index_del (Z_ARRVAL_P (return_value ), p-> h); 61} else {62 if (Z_ARRVAL_P (return_value) = & EG (symbol_table) {63 zend_delete_global_variable (p-> arKey, p-> nKeyLength-1 TSRMLS_CC); 64} else {65 zend_hash_quick_del (Z_ARRVAL_P (return_value), p-> arKey, p-> nKeyLength, p-> h ); 66} 67} 68} 69} 70 pefree (arTmp, Z_ARRVAL_P (array)-> persistent); 71} 72 /*}}}*/

We can see that this function initializes a new array, copies the value to the new array, and then calls the sorting function in row 45 to sort the array, the sorting algorithm is the block tree sorting algorithm of the zend Engine. Next, traverse the sorted array and delete repeated elements. The largest overhead of the entire function is called the sorting function, and the time complexity of the fast sorting is O (n * logn). therefore, the time complexity of this function is O (n * logn ).

Conclusion

Array_unique calls the quick sort algorithm at the underlying layer, which increases the time overhead of function running, resulting in slow operation of the entire function. This is why array_keys is faster than the array_unique function.

The original article is limited in writing, so it is easy to learn. if there is anything wrong with the article, please let us know.

If this article is helpful to you, click here for recommendations. it is not easy to write articles.

Previously, the article discussed how to implement PHP array de-duplication in a faster way in [Translation]. array_flip is used before calling arra...

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.