加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

数组实现办法:PHP5 VS PHP7

发布时间:2022-08-03 16:07:34 所属栏目:PHP教程 来源:互联网
导读:从 PHP 5 到 PHP 7 ,PHP 通过对 hashtable 数据结构和实现方式的修改,使得数组在内存占用和性能上有了很大的提升。 ⒈ 数据结构 void *pData; /*指向数组 value 的地址*/ void *pDataPtr; /*如果 value 为指针,则由 pDataPtr 记录 vlaue,pData 则指向 pD
    从 PHP 5 到 PHP 7 ,PHP 通过对 hashtable 数据结构和实现方式的修改,使得数组在内存占用和性能上有了很大的提升。
 
⒈ 数据结构
 
 
    void *pData; /*指向数组 value 的地址*/
 
    void *pDataPtr; /*如果 value 为指针,则由 pDataPtr 记录 vlaue,pData 则指向 pDataPtr*/
 
    // PHP 5 中数组元素的顺序是固定的,无论什么时候遍历,数组元素总是与插入时的顺序一致
 
    // PHP 5 中使用双向链表来保证数组元素的顺序,pListNext 和 pListLast 分别按照
 
    // 元素插入顺序记录当前 bucket 的下一个和上一个 bucket
 
    struct bucket *pListNext;
 
    struct bucket *pListLast;
 
    // PHP 5 使用拉链法解决 hash 碰撞,pNext 和 pLast 分别存储当前 bucket
 
    // 在冲突的双向链表中的下一个和上一个相邻的 bucket
 
    struct bucket *pNext;
 
    struct bucket *pLast;
 
    const char *arKey; /*关联数组是存储 key 的原始值*/
 
} Bucket;
 
 
 
typedef struct _hashtable {
 
    uint nTableSize; /*当前 ht 所分配的 bucket 的总数,2^n*/
 
    uint nTableMask; /*nTableSize - 1,用于计算索引*/
 
    uint nNumOfElements; /*实际存储的元素的数量*/
 
    ulong nNextFreeElement; /*下一个可以被使用的整数 key*/
 
    Bucket *pInternalPointer; /*数组遍历时,记录当前 bucket 的地址*/
 
    Bucket *pListHead;
 
    Bucket *pListTail;
 
    Bucket **arBuckets; /*记录 bucket 的 C 语言数组*/
 
    dtor_func_t pDestructor; /*删除数组元素时内部调用的函数*/
 
    zend_bool persistent; /*标识 ht 是否永久有效*/
 
    unsigned char nApplyCount; /*ht 允许的最大递归深度*/
 
    zend_bool bApplyProtection; /*是否启用递归保护*/
 
#if ZEND_DEBUG
 
    int inconsistent;
 
#endif
 
} HashTable;
 
 
 
// PHP 7 中 hashtable 的数据结构
 
// PHP 7 中个子版本以及阶段版本中对 hashtable 的数据结构的定义会有微小的差别,这里使用的是 PHP 7.4.0 中的定义
 
struct _zend_string {
 
    zend_refcounted_h gc;
 
    zend_ulong        h;  /*字符串 key 的 hash 值*/
 
    size_t            len;  /*字符串 key 的长度*/
 
    char              val[1]; /*存储字符串的值,利用了 struct hack*/
 
};
 
 
 
typedef struct _Bucket {
 
    zval              val;  /*内嵌 zval 结构,存储数组的 value 值*/
 
    zend_ulong        h;                /* hash value (or numeric index)   */
 
    zend_string      *key;              /* string key or NULL for numerics */
 
} Bucket;
 
 
            ZEND_ENDIAN_LOHI_4(
 
                zend_uchar    flags,
 
                zend_uchar    _unused,
 
                zend_uchar    nIteratorsCount,
 
                zend_uchar    _unused2)
 
        } v;
 
        uint32_t flags;
 
    } u;
 
    uint32_t          nTableMask; /*作用与 PHP 5 中 hashtable 中 nTableMask 作用相同,但实现逻辑稍有变化*/
 
    Bucket           *arData; /*存储 bucket 相关的信息*/
 
    uint32_t          nNumUsed; /*ht 中已经使用的 bucket 的数量,在 nNumOfElements 的基础上加上删除的 key*/
 
    uint32_t          nNumOfElements;
 
    uint32_t          nTableSize;
 
    uint32_t          nInternalPointer;
 
    zend_long         nNextFreeElement;
 
    dtor_func_t       pDestructor;
 
};
 
 
具体 PHP 5 数组的内存消耗情况,之前的文章已有讲解,这里不再赘述
 
  现在来谈谈 Bucket 的存储:在 PHP 5 中,arBucket 是一个 C 语言数组,长度为 nTableSize,存储的是指向 Bucket 的指针,发生 hash 碰撞的 Bucket 以双向链表的方式连接。

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读