zend によって PHP に与えられるすべての変数は構造的な方法で保存され、文字列の保存と配列の保存はハッシュ テーブルの形式で保存されます (ハッシュによって保存されたアドレスが効果的に競合を軽減できることは誰もが知っています)。 -hash ハッシュ テーブルの概念はご存知でしょう)、PHP の構造は次のとおりです:
コードをコピー コードは次のとおりです:
//ファイル 1: zend/zend.h
/*
* zval
*/
typedef struct _zval_struct zval
...
typedef Union _zvalue_value; {
long lval; /* long 値 */
double 値 */
struct {
int len; str; 🎜>HashTable *ht; /* ハッシュテーブル値 */
zend_object_value
} zvalue_value;
struct _zval_struct {
/* 変数情報 */
zvalue_value / * value * /
zend_uint refcount__gc;
zend_uchar type; /* アクティブなタイプ */
zend_uchar is_ref__gc;
} // ハッシュテーブルの構造は次のとおりです
// ファイル 2: zend/zend_hash.h
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
ulong nNextFreeElement; /*要素のトラバーサルに使用されます */
Bucket *pListTail;
zend_bool pDestructor; zend_bool bApplyProtection; if ZEND_DEBUG
int inconsistent;
#endif
}
HashTable;
一般変数 (文字列) が strlen を使用して長さを取得する場合、実際に取得される値は次のとおりです。 zvalue_value.str 構造体の len 属性は O(1) 回で効率的です。 特に注意すべき点は、strlen には PHP のコア実装がなく、zend のマクロ定義を使用して取得されることです。 >
コードをコピー
コードは次のとおりです:
//ファイル 3: zend/zend_operators.php
#定義 Z_STRLEN(zval ) (zval).value.str.len
配列のカウント操作に関しては、実際には 2 つの結果があります。2 番目のパラメーター モードは、カウント API「http://www.php.net」にも記載されています。 /manual/ja /function.count.php》、このモードパラメータは再カウントが必要かどうかを示し、再カウントは配列を 1 回走査し、デフォルトでは効率は O(N)[N: length] です。 、再カウントは必要ありません。その場合、ハッシュテーブル内の nNumOfElements がこの時点で直接出力され、この時点の効率も O(1) 倍になります。カウント コードは次のとおりです:
コードをコピー
コードは次のとおりです:
//ファイル 4: ext/standard/array.c
PHP_FUNCTION(count)
{
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; (配列, モード TSRMLS_CC));
break;
.. ...
//php_count_recursive の実装
static int php_count_recursive(zval *array, long mode TSRMLS_DC) /* { {{ */
{
long cnt = 0;
zval **element;
if (Z_TYPE_P(array) == IS_ARRAY) {
//エラー処理
if (Z_ARRVAL_P(array)->nApplyCount > 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "再帰が検出されました");
return
}
//長さを取得します。 zend_hash_num_elements
cnt = zend_hash_num_elements(Z_ARRVAL_P(array));
//再カウントが必要と指定されている場合、統計のサイクルに入ります
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(配列), &pos)
) {
Z_ARRVAL_P(配列) ->nApplyCount
cnt = php_count_recursive(*element, COUNT_RECURSIVE TSRMLS_CC); P(配列) ->nApplyCount--;
}
}
}
return cnt;
}
//ファイル 5: zend/zend_hash.c
//zend_hash_num_elements の実装
ZEND_API int zend_hash_num_elements(const HashTable *ht)
{
IS_CONSISTENT(ht)
return ht->nNumOfElements;