The content of this article is about the PHP7 kernel Anatomy 1 cgi and fastcgi, now share to everyone, the need for friends can refer to
1. Variable structure
typedef struct _ZVAL_STRUCT Zval;typedef Union _zend_value {Zend_long lval; int reshape double dval; Floating-point zend_string *str; string Strings Zend_array *arr; Array arrays Zend_object *obj; Object Objects Zend_resource *res; Resource resource type zend_reference *ref; Reference type, defined by & $var _name} zend_value;struct _zval_struct {zend_value value;//variable actual value Union {St ruct {zend_endian_lohi_4 (Zend_uchar type,//variable type Zend_uchar type _flags,//type mask, different types will have different properties, memory management will use Zend_uchar const_flags, Zend_uchar reserved) } V; uint32_t Type_info; The above 4 values of the combined value, can be directly based on Type_info to 4 corresponding to the value of the position} U1; Union {uint32_t Var_flags; uint32_t Next; Hash table in the resolution of the conflict with the uint32_t Cache_slot; uint32_t Lineno; uint32_t Num_args; uint32_t fe_pOs uint32_t Fe_iter_idx; } U2;};
2. Variable type
#define IS_UNDEF 0#define is_null 1#define is_false 2#define is_true 3#define is_long 4#define Is_double 5#define is_string 6#define is_array 7#define is_object 8#define is_resource 9# Define Is_reference 10
where undef, true, false, null have no value, are directly differentiated by type, and long, double values directly exist in value, other types are pointers
3. String
typedef struct _ZEND_STRING zend_string;struct _zend_string { zend_refcounted_h gc; Variable reference information, such as the current value reference number size_t len; string length, which guarantees binary security char val[1];//string content, variable length struct, allocate at len length for memory};
4. Arrays
typedef struct _zend_array hashtable;typedef struct _zend_array zend_array;typedef struct _bucket { zval val;// Stores the specific value, where a zval is embedded, instead of a pointer zend_ulong h; Hash value zend_string *key;//key value} bucket;struct _zend_array { zend_refcounted_h gc;//reference count information uint32_t Ntablemask; The mask for calculating the bucket index is used for the calculation of the hash table nindex bucket *ardata; Bucket array uint32_t nnumused; Number of buckets uint32_t nnumofelements;//number of elements, nnumofelements <= nnumused, because the deletion is not removed directly from the Ardata uint32_t ntablesize;//array size, 2^n, default 8 uint32_t ninternalpointer;//numeric index for Hashtable traversal Zend_ Long nnextfreeelement;//The number index of the next free available location dtor_func_t the pdestructor;//destructor, the function pointer that was called when it was destroyed};
Hashtable mainly relies on ardata to implement the storage and indexing of elements. Inserting an element first inserts the element in the bucket array in a sequential order, the position is IDX, and then maps to a location in the hash table according to the hash value of key nindex, and the idx is stored in this position; When the lookup is first mapped to nindex in the hash table, Get the value in the bucket array position idx, and then remove the element from the bucket array.
$arr ["a"] = 1; $arr ["b"] = 2; $arr ["c"] = 3; $arr ["d"] = 4;unset ($arr ["C"]);
Hash Collision: Saves the location of the original value to the Zval.u2.next of the new value when a conflict occurs, and then replaces the new value with the original value location
Expansion: PHP hash table size is 2^n, when inserted if the capacity is not enough to first check the proportion of deleted elements, if the threshold is reached, the deleted element is removed, rebuild the index, if not to the threshold of the expansion operation, expand to twice times the current size, the current bucket array to the new space , and then rebuild the index.
Rebuild Hash list: The hash list needs to be rebuilt when the deleted element reaches a certain number or expansion, because value moves in the bucket position or the hash array ntablesize changes, causing the mapping relationship between key and value to change. The rebuild process actually iterates through the value in the bucket array, then recalculates the mapped values to the hash table, removes the deleted value, and then moves forward the value that was not deleted
.
5. References
Reference is a special type of PHP, it is actually pointing to another PHP variable, its modification will directly change the actual point of the zval, can be easily understood as a pointer in C, in PHP through the & operator to produce a reference variable, that is, regardless of the previous type, & First creates a zend_reference structure with a zval embedded in it, which points to the value of the original Zval (if it is Boolean, reshape, floating point), and then modifies the original zval type to Is_ REFERENCE, the value of the original Zval points to the newly created zend_reference structure.
typedef struct _ZEND_REFERENCE zend_reference;struct _zend_reference { zend_refcounted_h gc; Zval Val;};
6. Reference counting
typedef struct _ZEND_REFCOUNTED_H { uint32_t refcount; Union { struct { zend_endian_lohi_3 ( zend_uchar type, zend_uchar flags, uint16 _t gc_info) } v; uint32_t type_info; } U;} Zend_refcounted_h;
$a = "Time:". Time (); $a -zend_string_1 (refcount=1) $b = $a; $a, $b -zend_string_1 (refcount=2) $c = $b; $a, $b, $c- zend_string_1 (refcount=3) unset ($b); $b = Is_undef $a, $c- zend_string_1 (refcount=2)
not all data types use reference counts, long, double are hard copies, and reference counts are used only if value is the type of pointer (except interned string,immutable array). Can be judged by Zval.u1.type_flag
7. Copy-On-write
$a = array, $b = & $a; $c = $a;//split $b[] = 3;
in fact, only string, array two support,
8. Garbage collection
There are two main types of recycling of PHP variables: active destruction, automatic destruction. Active destruction refers to unset, and automatic destruction is the automatic management mechanism of PHP, in return when the local variable refcount, even if there is no explicit return,php will automatically add this operation, the other is to write when the copy will break the original value point, The refcount of the old value after disconnection is also checked.
$a = [1]; $a [] = & $a; unset ($a);
unset ($a) reference relationship before:
After unset ($a):
Related recommendations:
PHP7 Kernel anatomy 1 cgi and fastcgi
PHP7 Core Profiling 2 I/O model