By accident, Baidu knows that a student asked about the efficiency of count and strlen. well, I didn't fully understand this problem at the beginning and thought it was not two different things that could not be compared, after reading the reply from the landlord, I checked the source code. Now summarize the results and record them. Zend stores all the variables in php in a structured manner, while saving strings is different from saving arrays, the array is saved as a hash table (you know the concept that the address saved by hash effectively reduces the conflict-hash list), and the structure in php is shown as follows:
The code is as follows:
// File 1: zend/zend. h
/*
* Zval
*/
Typedef struct _ zval_struct zval;
...
Typedef union _ zvalue_value {
Long lval;/* long value */
Double dval;/* double value */
Struct {
Char * val;
Int len;
} Str;
HashTable * ht;/* hash table value */
Zend_object_value obj;
} Zvalue_value;
Struct _ zval_struct {
/* Variable information */
Zvalue_value value;/* value */
Zend_uint refcount _ gc;
Zend_uchar type;/* active type */
Zend_uchar is_ref _ gc;
};
// The structure of the hash table is as follows:
// File 2: zend/zend_hash.h
Typedef struct _ hashtable {
Uint nTableSize;
Uint nTableMask;
Uint nNumOfElements;
Ulong nNextFreeElement;
Bucket * pInternalPointer;/* Used for element traversal */
Bucket * pListHead;
Bucket * pListTail;
Bucket ** arBuckets;
Dtor_func_t pDestructor;
Zend_bool persistent;
Unsigned char nApplyCount;
Zend_bool bApplyProtection;
# If ZEND_DEBUG
Int inconsistent;
# Endif
}
HashTable;
When strlen is used to obtain the length of a common variable (string), The len attribute in the zvalue_value.str structure is actually obtained, and the efficiency is O (1). It is particularly noted that: strlen has no core implementation in php, but is obtained by using the macro definition in zend:
The code is as follows:
// File 3: zend/zend_operators.php
# Define Z_STRLEN (zval). value. str. len
...
# Define Z_STRLEN_P (zval_p) Z_STRLEN (* zval_p)
...
# Define Z_STRLEN_PP (zval_pp) Z_STRLEN (** zval_pp)
In fact, there are two results for the count operation on the array. in the count api, the second parameter mode "limit (N) [N: length] is also mentioned. by default, nNumOfElements in hashtable will be directly output without re-statistics. The efficiency is also O (1) times: the count code is as follows:
The code is as follows:
// File 4: ext/standard/array. c
PHP_FUNCTION (count)
{
Zval * array;
Long mode = COUNT_NORMAL;
If (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "z | l", & array, & mode) = FAILURE ){
Return;
}
Switch (Z_TYPE_P (array )){
Case IS_NULL:
RETURN_LONG (0 );
Break;
Case IS_ARRAY:
RETURN_LONG (php_count_recursive (array, mode TSRMLS_CC ));
Break;
.....
// Php_count_recursive implementation
Static int php_count_recursive (zval * array, long mode TSRMLS_DC )/*{{{*/
{
Long cnt = 0;
Zval ** element;
If (Z_TYPE_P (array) = IS_ARRAY ){
// Handle errors
If (Z_ARRVAL_P (array)-> nApplyCount> 1 ){
Php_error_docref (NULL TSRMLS_CC, E_WARNING, "recursion detected ");
Return 0;
}
// Get the length directly through zend_hash_num_elements
Cnt = zend_hash_num_elements (Z_ARRVAL_P (array ));
// If the statistics need to be re-calculated, a cyclic statistics will be performed.
If (mode = COUNT_RECURSIVE ){
HashPosition pos;
For (zend_hash_internal_pointer_reset_ex (Z_ARRVAL_P (array), & pos );
Zend_hash_get_current_data_ex (Z_ARRVAL_P (array), (void **) & element, & pos) = SUCCESS;
Zend_hash_move_forward_ex (Z_ARRVAL_P (array), & pos)
){
Z_ARRVAL_P (array)-> nApplyCount ++;
Cnt + = php_count_recursive (* element, COUNT_RECURSIVE TSRMLS_CC );
Z_ARRVAL_P (array)-> nApplyCount --;
}
}
}
Return cnt;
}
// File 5: zend/zend_hash.c
// Zend_hash_num_elements implementation
ZEND_API int zend_hash_num_elements (const HashTable * ht)
{
IS_CONSISTENT (ht );
Return ht-> nNumOfElements;
}