Structure diagram of Hash table:
Found in: Bucket1 and Bucket2 are hash conflicting doubly linked list, but after adding Bucket2 is added to the head, you can see Bucket2 plistlast and Pnext point to Bucket1.
The field interpretation of the Hashtable struct:
1.nTableSize. As the name implies, this is the size of the entire hash table allocation (in the internal implementation of the array size allocated in C, PHP is dynamic, but the layer array is the size of the static), his size has a fixed application algorithm, generally the closest and greater than the current value of 2 of the powers, the description may be a bit vague, For example, if the PHP array stores 32 of the shaping data, then the ntablesize of the underlying application should be equal to 32 elements, if 33, then the most recent and greater than the number of a number 64, then the size of the allocation is 64 elements. The reason for this allocation is to allocate enough memory and not to waste too much memory. Hash-based efficiency considerations, too small then bound to cause a hash after too much collision lookup, if the allocation is too large then it is necessary to waste too much memory, so the allocation has been proven relatively in space and time to achieve a balance.
2.nTableMask. The mask value of the hash table equals nTableSize-1, what is his role? The correct index value used to correct the hash value computed by the DBJ algorithm in the hash table of the current ntablesize size. For example, "foo" by the fixed algorithm after the hash value is 193491849, if the size of the table is 64, it is clear that the maximum index value, it is necessary to use the mask of the hash table to correct the actual use of the method is to do with the mask bit and operation, This is done in order to map the hash value as large as the ntalbesize space.
Hash | 193491849 | & Mask | & | & 0b0000000000000000000000111111------------------------------------------ ---------------= Index | = 9 | = 0b0000000000000000000000001001
3.nNumOfElements. is the number of actual stored elements in the PHP array, and we use count,sizeof to calculate the value obtained.
4.nNextFreeElement. The next free element space is required when we apply for an empty subscript element, such as $ret[] = ' apple '.
5.pInternalPointer. A pointer to the elements currently executing inside is stored, which is used when we use some internal loop functions such as reset (), current (), Prev (), Next (), foreach (), End ().
6.pListHead and Plisttail point to the first and last element of the hash table, corresponding to the starting and ending elements of the array.
7.arBuckets. This is the inner array of the actual stored C. Here is a pointer to the pointer bucket * *. That points to an array of pointers, where each element is a head pointer to a bucket list.
8.pDestructor is a destructor that fires when a value is deleted from a hash table. He also has a major role for GC recycling of variables. In PHP, the GC is implemented by reference counting, and when a variable's reference count becomes 0, it is recycled by the PHP GC.
9.persistent defines whether the hashtable can be persisted in multiple request.
10.nApplyCount and bapplyprotection are used to prevent infinite recursion.
11.inconsistent is to capture the incorrect use of HT in debug mode.
Definition of Hashtable in ZEND/ZEND_HASH.H:
typedefstruct_hashtable {UINTNtablesize;//the size of the hash bucket, with a minimum of 8, increases by 2x. UINTNtablemask;//NTableSize-1, a mask that is used to calculate the storage location based on the hash value. UINTnnumofelements;//The number of elements currently present in the hash bucket, and the count () function returns this value directly ULONGNnextfreeelement;//The position of the next numeric index, which is used when $arr [] = "Hello"Bucket *pinternalpointer;//the currently traversed pointer (one of the reasons why foreach is faster than for a)Bucket *plisthead;//storing array header element pointersBucket *plisttail;//store array tail element pointerBucket **arbuckets;//Storing hash arraysdtor_func_t Pdestructor; Zend_bool persistent; unsignedCharNapplycount;//marks the number of times the current hash bucket has been accessed recursively (prevents multiple recursion)Zend_bool bapplyprotection;//mark the current hash bucket allows multiple accesses are not allowed, up to 3 times can be recursive when not allowed#ifZend_debugintinconsistent;#endif} HashTable;
Explanation of the Bucket structure field:
1.h is a hash value, not a masked corrected hash DBJ the original value.
2.arKey, which is used to record the string as a hash, nkeylength is the length of the hash string, which is not used for shaping key values.
3.pData and Pdataptr are pointers to the actual data stored in PHP, where they usually point to a zval structure (which is widely used by PHP to store various variables and objects internally).
4.pListNext, Plistlast Specifies the order of the entire array, and the traversal in PHP is through the Plisthead bucket in the hash structure, traversing the pnext until the end of the array.
5.pNext and Plast These two pointers are used to solve the hash conflict, this is described in detail in the following hashing conflict, in the PHP hash table conflict processing uses the Zipper method is to pull a linked list at each possible conflicting key value location to store the corresponding key value data.
Definition of buckets in ZEND/ZEND_HASH.H:
typedefstructBucket {/*used for numeric indexing*/ ULONGH//The value after the hash of the Char *key, or the user-specified numeric index value UINTNkeylength;//The length of the hash keyword, if the array index is a number, this value is 0 void*pdata;//point to value, which is typically a copy of the user's data , or, in the case of pointer data, to PDATAPTR void*pdataptr;//if it is a pointer data, this value points to the true value, and the above pdata points to this value structBucket *plistnext;//The next element of the entire hash table structBucket *plistlast;//The entire hash table the previous element of the element structBucket *pnext;//the next element stored in the same hash bucket structBucket *plast;//the previous element of the same hash bucket Chararkey[1]; /*Store character index, this item must be placed at the least, because here only the meaning of 1 bytes, the storage is actually point to the value of char *key, which means that you can save the re-assignment once the consumption, and sometimes this value does not need, so at the same time also save space. */} buckets;
PHP hash Table (a) hash table structure