热搜:NVER node 开发 php

《PHP核心技术与实践》PHP内核中的HashTable分析

2024-07-24 11:20:01
《PHP核心技术与实践》PHP内核中的HashTable分析

  1. HashTable是PHP的灵魂,因为在Zend引擎中大量地使用了HastTable,如变量表,常量表,函数表,数组等,所以了解HashTable对真正了解PHP很重要!
  2. PHP内核中HashTable的数据结构: PHP的HashTable同时维护一个双向链表,而这个双向链表是通过pListNext和pListLast这两个成员变量维护的。 成员变量中,pData和pDataStr较容易混淆,pData指向的是想要保存的内存块地址,一般是通过malloc之类的系统调用分配出来,但是有时候只想保存一个指针,如果这样也去调用malloc之类的系统调用分配内存会导致产生内存碎片,这种情况PHP内核是不能容忍的,所以出现了pDataPtr指针。pDataPtr的指针就是当想保存一个指针类型的数据时,就直接保存到pDataPtr成员变量中,而不调用malloc分配内存,从而防止了内存碎片的产生,然后pData直接指向pDataPtr,当要保存的数据不是指针时,pDataPtr被设置为NULL.

要找到某个保存在HashTable中的数据,则是通过索引(key),每个元素都有一个索引且不同,通过索引可以找到这个元素且可取得保存在里面的数据。索引保存在HashTable的最后一个成员arKey起始位置的长nKeyLength的内存中,虽然arKey只有一个字节,但这里使用了C语言的一个常用技巧(flesible array),通过申请sizeof(Bucket)+nKeyLength大小的内存,然后把索引保存到arKey成员中。

但如果索引为整数,本来也可以把整数当成字符串处理,但PHP不这样做,而是利用一个技巧来解决。当索引为整数时,PHP把索引保存到Bucket结构体的h成员变量中,然后把nKeyLength设置为0,表示这是一个整数而不是字符串,所以当nKeyLength大于0时,可在arKey中取到索引,而当nKeyLength等于0时,就在h中取得索引,那当nKeyLength为0时h成员变量是不是没有用呢?其实不然,当nKeyLength大于0时(索引为字符串时),h成员保存的是索引经过hash函数处理之后的值,这样做的好处就是,在重hash时不用重新计算索引的hash值。(hash函数得到的是一个整形数,所以可以保存在ulong h;中,可用来做下标)

  1. HashTable结构体分析,几图示: