深入PHP-直观观察array的扩展

      皆知PHP的数组是由HashTable和双链表实现的,为了方便大家查看数组的数据结构,开发一个遍历PHP的数组生成Dot描述的PHP插件,生成dot描述以后可以通过一些渲染工具生成图像,本例用的是 Graphviz。 
        扩展的实现很简单,PHP数组源码是由下面的两种结构体实现的,扩展就是将这两种结构体和各个结构体的关系遍历一遍,生成对应的Dot描述即可。 
Java代码  技术分享
  1. typedef struct bucket {  
  2.      ulong h;                           
  3.      uint nKeyLength;  
  4.      void * pData;  
  5.      void * pDataPtr;  
  6.      struct bucket * pListNext;  
  7.      struct bucket * pListLast;  
  8.      struct bucket *pNext ;  
  9.      struct bucket * pLast;  
  10.      const char *arKey ;  
  11. } Bucket;  
  12.   
  13. typedef struct _hashtable {  
  14.      uint nTableSize;  
  15.      uint nTableMask;  
  16.      uint nNumOfElements;  
  17.      ulong nNextFreeElement;  
  18.      Bucket *pInternalPointer;      
  19.      Bucket *pListHead;  
  20.      Bucket *pListTail;  
  21.      Bucket **arBuckets;  
  22.      dtor_func_t pDestructor;  
  23.      zend_bool persistent;  
  24.      unsigned char nApplyCount ;  
  25.      zend_bool bApplyProtection;  
  26. } HashTable;  
  27.    



扩展里边函数说明 
--------------------------------------------------------------------------------------------- 
string    dotarray( array $input [, int $flag] ) 
生成数组数据结构的dot描述 
参数 
input   需要操作的数组 
flag   查看那些数据结构,是扩展提供的3个常量或操作,分别是 
     DOTARAAY_HASH_TABLE 表示显示HashTable结构 
     DOTARRAY_DOUBLE_LIST 显示数组的双链表结构 
     DOTARRAY_CURRENT_POSITION 显示数组现在的内部指针的位置 
返回值 
成功返回dot描述字符串,错误(非数组等情况)返回false 
--------------------------------------------------------------------------------------------- 
显示双链表结构例子 

Java代码  技术分享
  1. <?php  
  2.   
  3. $items = array(1,2,8=>‘lalala‘,16=>‘hahaha‘,‘name‘=>‘shiki‘,30=>‘wooooo...‘);  
  4. next($items);/*将内部指针移到下一位*/  
  5. $result = dotarray($items,DOTARRAY_DOUBLE_LIST|DOTARRAY_CURRENT_POSITION);  
  6. echo  $result;  

得到的dot描述: 

Java代码  技术分享
  1. digraph html {label = "Structure of array";  
  2. node[shape = record];  
  3. ===========部分内容省略============  
  4. edge [color=black];  
  5. edge [color=green];  
  6. sk_array:f5:s -> sk_item_1:f0;  
  7. edge [color=black];  
  8. }  

通过graphviz渲染得到下面的图片 

技术分享


需要解释一下,红色实线为结构中双链表的next指针,红色点线为上一个元素指针。同时提供了DOTARRAY_CURRENT_POSITION标志,出现绿线指向数组内部指针指向key为1的元素(第一个元素key为0) 

显示HashTable结构例子 

Java代码  技术分享
  1. <?php  
  2.   
  3. $items = array(1,2,8=>‘lalala‘,16=>‘hahaha‘,‘name‘=>‘shiki‘,30=>‘wooooo...‘);  
  4. next($items);  
  5. next($items);  
  6. $result = dotarray($items,DOTARAAY_HASH_TABLE|DOTARRAY_CURRENT_POSITION);  
  7. echo $result;  

生成的结构图片如下: 

技术分享

hash冲突的例子 
       具体可以参考 PHP hash碰撞拒绝服务漏洞原理http://www.laruence.com/2011/12/29/2412.html,简单介绍即是:Hash表因为”冲突”(碰撞)而退化成链表,如果数据量足够大, 使得php在计算, 查找, 插入的时候, 造成大量的CPU占用, 从而实现拒绝服务攻击。下面是简单的碰撞生成代码: 

<
Java代码  技术分享
  1. ?php  
  2.   
  3. /*会生出pow(2,$n)个数字*/  
  4. $n= 3;  
  5. $capacity = pow(2,$n);  
  6. $array =array();  
  7. for($i=0;$i<$capacity;$i++){  
  8.     $key = $i<<$n;  
  9.     $array[$key] =1;  
  10. }  
  11.   
  12.   
  13. $str = dotarray($array,DOTARRAY_DOUBLE_LIST|DOTARAAY_HASH_TABLE);  
  14. echo $str,PHP_EOL;  

这次将hashtable和双线表同时展示出来,传递的flag为DOTARRAY_DOUBLE_LIST|DOTARAAY_HASH_TABLE,同时展示双链表和HashTable 

技术分享

关于 dot语言 传送门:http://zh.wikipedia.org/wiki/DOT%E8%AF%AD%E8%A8%80 

关于 dot渲染工具Graphviz 传送门:http://www.graphviz.org/


扩展源码:https://github.com/Himer/dotarray

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。