PHP5的链表是物理上的链表,链表中的bucket之间的上下游关系通过真实存在的指针维护。而PHP7的链表是一种逻辑上的链表,所有的bucket都分配在连续的数组内存中,不再通过指针维护上下游关系,每一个bucket只维护下一个bucket在数组中的索引(因为是连续内存,通过索引可以快速定位到bucket),即可完成链表上bucket的遍历。
5.3.1 基本结构
val:对应hashTable里面的value,始终是zval类型。
h:对应hashTable中的h,表示数字key或字符串key的h值。
key:对应hashTable中的key,表示字符串key。
区别于PHP5,不再是char*,而是指向zend_string的指针,提高了性能和空间效率
bucket从使用角度可以分为:
未使用bucket:最初的所有bucket都是未使用bucket
有效bucket:存储着有效的数据(key, val, h),当进行插入时,会选择一个未使用bucket,这样该bucket就变成了有效bucket。更多新操作只能发生在有效bucket上
无效bucket:当bucket上的数据被删除,有效bucket就会变成无效bucket。对于某些场景的插入(packed array 的插入),除了会生成一个有效 bucket 外,还会有副作用,生成多个无效 bucket
在内存分布上,有效 bucket 和无效 bucket 会交替分布,但都在未使用 bucket 的前面。
插入的时候永远在未使用 bucket 上进行。
当由于删除等操作,导致无效 bucket 非常多,而有效 bucket 很少时,会对整个 bucket 数组进行 rehash 操作。稀疏的有效 bucket 就会变得连续而紧密,部分无效 bucket 会被重新利用而变为有效 bucket,还有一部分有效 bucket 和无效 bucket 会被释放出来,重新变为未使用 bucket。
HashTable结构
gc:引用计数
arData:实际的存储容器。通过一段连续的内存,存储着bucket数组
nTableSize:HashTable的大小。表示arData指向的bucket的大小,即所有bucket的数量