php源码学习 数组变量

一、hashArray vs packedArray

  1. $arr1 是packed arrray 本身就是有顺序的
  2. $arr2 是hash array需要做散列来保证数组的存取顺序
    1. $arr1 = [];
      for ($i = 0; $i <= 200000; $i++) {
          $arr1[$i] = $i;
      }
      
      $arr2 = [];
      for ($i = 200000; $i >= 0; $i--) {
          $arr2[$i] = $i;
      }

  3. $arr2 比$arr1 多占用的内存为图示用于做散列的部分
  4. 默认8个bucket,如果索引数组的下标不超过8使用packed array存储即可,留出空余位置即可。超过8为了不浪费空间,会转化为hash array
    1. <?php
      $a = [1, 2, 3];
      $a[5] = 5;
      echo $a;
      
      $b = [1, 2, 3];
      $b[10] = 10;
      echo $b;

二、数组hashTable

解决hash冲突:拉链法(头插法,不用遍历)

问题:冲突过多时时间复杂度会有O1降到On

解决方法:rehash,把链表换成红黑树等其他数据结构

三、zval复杂类型的gc都会存一下类型

空间换时间

不知道类型的变量可强转gc,直接拿到类型

四、php的数组类型

typedef struct _zend_array HashTable;
struct _zend_array {	
     zend_refcounted_h gc;	// 垃圾回收,应用计数
     union u;	
     uint32_t       nTableMask;// 用来做散列	
     Bucket         *arData; // 存key-value对的桶	
     uint32_t       nNumUsed; // 元素个数,unset不会减少
     uint32_t       nNumOfElements; // 真正有意义的元素个数,unset会减少
     uint32_t       nTableSize;	// 大小,默认8,不够用两倍扩容
    uint32_t       nInternalPointer;	
    zend_long      nNextFreeElement; // 当前已用的数组下标	
    dtor_func_t    pDestructor;
};

typedef struct _Bucket {	
     zval             val;	// 任意类型zval
     zend_ulong        h;  // packed array            
     zend_string      *key; // hash array           
} Bucket;

五、PHP中的HashTable

  1. php7采用逻辑链表解决hash冲突
  2. 计算hash array 槽的方式:nTableMask 或 key通过的hash算法算出来的hash值

六、gdb 查看PHP中的HashTable(set print pretty on 可显示格式化的数据)

$a = [];
echo $a;
$a['k1'] = 'v1';
echo $a;
$a[] = 1;
echo $a;
$a[] = 2;
echo $a;
$a[] = 3;
echo $a;
unset($a[0]);
echo $a;
$a[5] = 5;
echo $a;
  1. 初始化$a=[];

  1. 添加第一个元素$a['k1'] = 'v1';

  1. 添加第二个元素$a[] = 1;

  1. 添加第三个元素$a[] = 2;

  1. 添加第四个元素$a[] = 3;

  1. 删除第二个元素unset($a[0]);

  1. 增加第五个元素$a[5] = 5;

  1. 增加第六个元素$a['6'] = 6;

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值