Heim  >  Artikel  >  Backend-Entwicklung  >  Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)

Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)

藏色散人
藏色散人nach vorne
2021-06-10 14:50:132489Durchsuche

Dieser Artikel stellt Ihnen „Analyse des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)“ vor. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

Empfohlene verwandte Artikel: „Analyse des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (1)“ „Analyse des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (3)“ „Analyse des zugrunde liegenden PHP8-Kernel-Quellcodes – Array ( 4)"

zend_array ist in PHP in zwei Typen unterteilt

1.packed array
2.hash array

在上文中 补齐了zend_array的 所有值的 注释

Tatsächlich unterscheidet sich die Reihenfolge im Quellcode geringfügig von meiner oben. Ich denke, meine oben Die Reihenfolge ist vernünftiger zu verstehen

//源码里的代码
typedef struct _zend_array HashTable;
struct _zend_array {
zend_refcounted_h gc;
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar    flags,
zend_uchar    _unused,
zend_uchar    nIteratorsCount,
zend_uchar    _unused2)
} v;
uint32_t flags;
} u;
uint32_t          nTableMask;
Bucket           *arData;
uint32_t          nNumUsed;
uint32_t          nNumOfElements;
uint32_t          nTableSize;
uint32_t          nInternalPointer;
zend_long         nNextFreeElement;
dtor_func_t       pDestructor;
};
//我调换下顺序后的代码
struct _zend_array {
zend_refcounted_h gc; 
 ///  gc  占用8个字节 用于引用计数和  字符串类型的记录
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar    flags,
// flags   8位的无符号字符, 最大值为255   标记HashTable用 PHP8 中有6个值
zend_uchar    _unused,
zend_uchar    nIteratorsCount,
//迭代器计数。foreach语句会在全局变量EG中创建一个迭代器,
//迭代器包含正在遍历的HashTable和游标信息。
//nIteratorsCount记录了当前runtime正在迭代当前HashTable的迭代器的数量。
zend_uchar    _unused2)
} v;
  //这里有点不一样 看陈雷大佬书中 v结构体还包括 u.v.nApplyCount和u.v.consistency
uint32_t flags;
             //
} u;
// u是是一个联合体。占用4个字节。
//可以存储一个uint32_t类型的flags,也可以存储由4个unsigned char组成的结构体v,
//这里的宏ZEND_ENDIAN_LOHI_4是为了兼容不同操作系统的大小端,可以忽略。
Bucket           *arData;
//HashTable中存储数据的单元的指针。
//  用来存储key和value以及辅助信息的容器。
uint32_t          nTableSize;
//    HashTable的大小。表示arData指向的bucket数组的大小,即所有bucket的数量。
//该字段取值始终是2n,最小值是8,最大值在64位系统中是0x80000000(2的31次幂)。
uint32_t          nNumUsed;
//指所有已使用bucket的数量,包括有效bucket和无效bucket的数量
uint32_t          nNumOfElements;
//有效bucket的数量。该值总是小于或等于nNumUsed
uint32_t          nTableMask;
//索引大小。一般值为  -nTableSize。
uint32_t          nInternalPointer;
//全局默认游标。reset/key/current/next/prev等宏 和操作都会用到
zend_long         nNextFreeElement;
//下一个插入的元素的key的下标  
//比如  当$a[] = 1  nNextFreeElement =1  
dtor_func_t       pDestructor;
//指向一个函数   typedef void (*dtor_func_t)(zval *pDest);
//可以看出是pDest是zval结构指针二级指针,
//为什么会是二级指针,因为c语言函数传递都是值传递,要改变指针值只能将指针地址传入
//当bucket元素被更新或者被删除时,会对bucket的value调用该函数,
//如果value是引用计数的类型,那么会对value引用计数减1,进而引发可能的gc。
};

Verwenden Sie das vom Verstehenstool generierte Mitgliedsvariablendiagramm wie folgt

Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)

Nach der gesamten Erweiterung lautet es wie folgt

Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)

Zend_array-Strukturmitglied

Das ist zu sehen Der Kern ist eigentlich z_val +zend_string +zend_refcounted_h+Bucket, das Schicht für Schicht verknüpft ist

wo Bucket gespeichert ist. Die Schlüsselinformationen des Arrays

typedef struct _Bucket {
zval              val;   //数组的值 ( 复习下 zval只有16个字节)
zend_ulong         h;     // key的 h  值
zend_string      *key;      //当数组为 hash_array时候 会用到 也就是 key的值  
} Bucket;

Egal, ob der Array-Typ gepacktes_array oder hash_array ist, das wird es schließlich im Bucket gespeichert werden

Wenn die Schlüssel alle numerische Tasten sind und die Schlüssel in der Einfügereihenfolge aufsteigen, ist der Array-Typ packed_array

Eigenschaften eines gepackten Arrays

  1. Das Array muss nicht indiziert werden
  2. Kein Schlüssel erforderlich
  3. Der h-Wert des Arrays ohne Schlüssel entspricht direkt dem Sortierwert des Speicherplatzes im Bucket ab 0
  4. key Der h-Wert des Arrays von -value Paare entsprechen dem Inhalt des Schlüssels

Das dritte und vierte Element können in PHP als Arrays verstanden werden. Wenn der Schlüssel nicht geschrieben ist, wird der Standardschlüssel beginnend bei 0

$a =array(1,2,3);  // packed array
$b =array(1=>'a',3=>'b',5=>'c'); //packed array
Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)

bucket Vor dem Array befindet sich ein Indexarray.

Wenn es sich um ein gepacktes Array handelt, beträgt die Größe des Indexarrays immer 2, da es nicht verwendet wird.

Der Inhalt im zend_array entsprechend $a oben ist

Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)
$a zend_array

nTableSize; stellt die Größe des Bucket-Arrays dar, auf das arData zeigt, also die Anzahl aller Buckets. = Die Gesamtgröße des Arrays nNnumused; bezieht sich auf die Anzahl aller Buckets, einschließlich der Anzahl gültiger und ungültiger Buckets.

Bucket, es gibt drei Zustände, die wirksam und ineffektiv sind.

So nNumOfElements+nNumUsed =nTableSize

nTableMask; Da das gepackte Array keinen Index verwendet, ist es immer -2

nNextFreeElement. Der Index des Schlüssels des nächsten eingefügten Elements. Das gepackte Array nutzt die Kontinuitätseigenschaften des Bucket-Arrays, um bestimmte Szenarien nur mit numerischen Schlüsseln zu optimieren . . Da das Index-Array nicht mehr benötigt wird, werden (nTableSize-2)* sizeof(uint32_t) Bytes aus dem Speicherplatz gespart. Da der Zugriff auf den Bucket das Bucket-Array direkt betreibt, wird außerdem auch die Leistung verbessert.

Wenn die Bedingungen eines gepackten Arrays nicht erfüllt sind, wird das Array in PHP durch hash_array dargestellt

Alle Schlüsselwerte, die nicht numerisch sind, werden durch hash_array dargestellt

$c =array('x'=>1,'y'=>2,'z'=>3,'a'=>0);

$c oben wird durch hash_array dargestellt

Bucket ist wie folgt

Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)
$c Bucket

zend_array ist wie folgt

Parsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2)
$c zend_array

nTableSize ; Gibt die Größe des Bucket-Arrays an, auf das arData zeigt, also die Anzahl aller Buckets. =8

nNumUsed; Bezieht sich auf die Anzahl aller verwendeten Buckets, einschließlich der Anzahl gültiger Buckets und ungültiger Buckets =4

NumOfElements; =4

So nNumOfElements+nNumUsed =nTableSize

nTableMask; -8

nNextFreeElement; Der Index des Schlüssels des nächsten eingefügten Elements hash_array ist immer 0, wenn er nicht verwendet wird

▏Dieser Artikel wurde vom ursprünglichen Autor PHP Cui Xuefeng genehmigt und auf der PHP-Chinese-Website veröffentlicht Die ursprüngliche Adresse lautet: https://zhuanlan.com/p/358354087

Das obige ist der detaillierte Inhalt vonParsen des zugrunde liegenden PHP8-Kernel-Quellcodes – Array (2). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:zhihu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen