• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

PHP源代码数组统计count分析_php技巧

php 搞代码 4年前 (2022-01-26) 15次浏览 已收录 0个评论

zend给php的所有变量都用结构的方式去保存,而字符串的保存和数组的保存也是不同的,数组采用的是hash表的方式去保存(大家知道hash保存的地址有效的减少冲突-hash散列表的概念你懂的),而在php中的结构体上表现如下:

 <BR>//文件1:zend/zend.h <BR>/* <BR>* zval <BR>*/ <BR>typedef struct _zval_struct zval; <BR>... <BR>typedef union _zvalue_value { <BR>long lval; /* long value */ <BR>double dval; /* double value */ <BR>struct { <BR>char *val; <BR>int len; <BR>} str; <BR>HashTable *ht; /* hash table value */ <BR>zend_object_value obj; <BR>} zvalue_value; <br><br>struct _zval_struct { <BR>/* Variable information */ <BR>zvalue_value value; /* value */ <BR>zend_uint refcount__gc; <BR>zend_uchar type; /* active type */ <BR>zend_uchar is_ref__gc; <BR>}; <BR>//hash表的结构如下 <BR>//文件2:zend/zend_hash.h <BR>typedef struct _hashtable { <BR>uint nTableSize; <BR>uint nTableMask; <BR>uint nNumOfElements; <BR>ulong nNextFreeElement; <BR>Bucket *pInternalPointer; /* Used for element traversal */ <BR>Bucket *pListHead; <BR>Bucket *pListTail; <BR>Bucket **arBuckets; <BR>dtor_func_t pDestructor; <BR>zend_bool persistent; <BR>unsigned char nApplyCount; <BR>zend_bool bApplyProtection; <BR>#if ZEND_DEBUG <BR>int inconsistent; <BR>#endif <BR>} <BR>HashTable; <BR>


一般的变量(字符串)在使用strlen获取长度的时候,其实获取的就是zvalue_value.str这个结构中的len属性,效率上O(1)次,特别说明的一点是:strlen在php中并没有核心的实现,而是在使用了zend中的宏定义来获取:

 <BR>//文件3:zend/zend_operators.php <BR>#define Z_STRLEN(zval) (zval).value.str.len <BR>... <BR>#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p) <BR>... <BR>#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp) <BR>


而对于数组的count操作,其实有两种结果,在count 的api中也提到了第二个参数mode《http://www.php.net/manual/en/function.count.php》,这个mode参数指明了,是否需要重新统计,而它的重新统计将会遍历一次数组,效率上是O(N)[N:长度],默认情况下是不重新统计,那这个时候将会直接输出hashtable中的nNumOfElements,此时的效率也是O(1)次:count代码如下:

 <BR>//文件4:ext/standard/array.c <BR>PHP_FUNCTION(count) <BR>{ <BR>zval *array; <BR>long mode = COUNT_NORMAL; <br><br>if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &mode) == FAILURE) { <BR>return; <BR>} <br><br>switch (Z_TYPE_P(array)) { <BR>case IS_NULL: <BR>RETURN_LONG(0); <BR>break; <BR>case IS_ARRAY: <BR>RETURN_LONG (php_count_recursive (array, mode TSRMLS_CC)); <BR>break; <BR>..... <br><br>//php_count_recursive的实现 <BR>static int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */ <BR>{ <BR>long cnt = 0; <BR>zval **element; <br><br>if (Z_TYPE_P(array) == IS_ARRAY) { <BR>//错误处理 <BR>if (Z_ARRVAL_P(array)->nApplyCount > 1) { <BR>php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected"); <BR>return 0; <BR>} <BR>//通过zend_hash_num_elements直接获得长度 <BR>cnt = zend_hash_num_elements(Z_ARRVAL_P(array)); <br><br>//如果指定了需要重新统计,则会进入一次循环统计 <BR>if (mode == COUNT_RECURSIVE) { <BR>HashPosition pos; <br><br>for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); <BR>zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **) &element, &pos) == SUCCESS; <BR>zend_hash_move_forwa<strong style="color:transparent">本&文来源gao@daima#com搞(%代@#码网@</strong><textarea>搞gaodaima代码</textarea>rd_ex(Z_ARRVAL_P(array), &pos) <BR>) { <BR>Z_ARRVAL_P(array)->nApplyCount++; <BR>cnt += php_count_recursive(*element, COUNT_RECURSIVE TSRMLS_CC); <BR>Z_ARRVAL_P(array)->nApplyCount--; <BR>} <BR>} <BR>} <br><br>return cnt; <BR>} <br><br>//文件5:zend/zend_hash.c <BR>//zend_hash_num_elements的实现 <BR>ZEND_API int zend_hash_num_elements(const HashTable *ht) <BR>{ <BR>IS_CONSISTENT(ht); <br><br>return ht->nNumOfElements; <BR>} <BR>

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:PHP源代码数组统计count分析_php技巧
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址