PHP数组的低内存利用和弱类型的详细解释

这两天的任务提前完成了。你可以自由的呼吸,平静下来,学习PHP的深度。事实上,我想知道关于PHP的性能优化的东西,但互联网上的PHP数组的内存利用率低,C语言100MB存储阵列,1G是需要在PHP。PHP是非常消耗内存的这么多因此,我们借此机会了解PHP数据类型实现的方式。



首先,做一个测试:


< PHP
回声memory_get_usage(),;
开始memory_get_usage美元=();
$ =数组();
($ i = 0;$ i < 1000;$ + +){
一美元;
}
美元= memory_get_usage();
回声memory_get_usage(),;
echo'argv:'($结束至开始) / 1000,'bytes ',';


结果如下:

三十五万三千三百五十二

四十三万七千八百四十八

参数:84.416bytes



1000要素成本存储整数数组(437848-353352)字节,这是82kb,这意味着每个元素占84个字节的内存,在C语言中,一个int占用4个字节,和整体差20倍。



但在互联网上,对memery_get_usage结果()不仅是数组占用,而且PHP本身的结构。因此,在另一方面,我们尝试使用PHP内置函数生成数组。


< PHP
开始memory_get_usage美元=();
(0, 10000, 1)array_fill美元=;
美元= memory_get_usage(); / /10公里元件阵列;
echo'argv:'($结束至开始) / 10000,'byte ',';


输出是:

参数:54.5792byte



不仅仅是好的能力,还有54字节,真的坏了10倍左右。



它的原因是说它的php.php底是弱类型语言,无论int,双,字符串等,统一的$可以解决所有的问题。PHP的底部是由C语言实现,每个点对应一个zval结构,它的定义是详细:


_zval_struct zval结构定义;
结构_zval_struct {
变量信息
zvalue_value价值; / *值112字节(32位机,12, 64位8 + 4 + 4 = 16)。
zend_uint refcount__gc;对这 /值的引用数(GC)4字节。
zend_uchar型主动式; / * * / 1字节
zend_uchar is_ref__gc这个值是否是一个; / *参考(1字节)。
};



PHP用联合结构存储变量的值,并在zval的zvalue_value型变量的值是一个联盟,定义如下:


_zvalue_value { typedef联盟
长语句长值; / * * /
双双双值; / * * /
字符串值
字符*;
Int len;
STR };
哈希表*哈希表值; / * * /
zend_object_value obj; / *对象的值。
zvalue_value };



联盟的类型占内存的大小是由其最大成员国的数据空间的确定。在zvalue_value,为4字节的STR结构账户和4个字节的字符指针的帐户的int,所以整个zvalue_value是8字节的内存。



机制的大小为8 + 4 + 1 + 1 = 14字节。



注意,有一zvalue_value哈希表什么在变量,数组,字符串,和对象需要一个存储结构和数组的存储结构是HashTable。



哈希表的定义了:


_hashtable { typedef struct
单位ntablesize; / /表长度,元素的数目不
单位ntablemask; / /面具等于ntablesize-1
单位nnumofelements; / /存储元素的个数
页nnextfreeelement; / /指针位置下空
斗* pinternalpointer; / / foreach循环,用于记录当前遍历元素的位置
plisthead斗*;
plisttail斗*;
斗* arbuckets; / /存储单元阵列
dtor_func_t pdestructor; / /析构函数
zend_bool执着; / /是持久的。从中,可以发现PHP数组可以实现持久存在内存中的每一个请求没有重装。
unsigned char napplycount;
zend_bool bapplyprotection;
哈希表};



除了记录表的大小和元素个数的几个属性变量外,还多次使用桶,以及如何定义桶:


typedef struct斗{
页H; / /数组索引
单位nkeylength; / /字符串索引的长度
void * pData; / /实际数据的存储地址
void * pdataptr; / /数据存储地址的介绍
结构plistnext斗*;
结构plistlast斗*;
结构斗* pnext; / /双向链表的地址的下一个元素
结构斗*塑料; / /下一个元素的地址双向链表
字符都可以实现{ 1 }必须是最后一个元素; / * * /
桶};


这有点像链接列表。水桶就像一个列表节点。它有具体的数据和指针。哈希表是一个串桶元件阵列。PHP中的多维数组的实现就是另一个哈希桶。



一个计算哈希表占用39字节,斗需要33个字节。一个空数组需要占用14 + 39 + 33 = 86字节。斗占33个字节,超过四字节的额外债券背后桶长度,和元素的值可能是zval结构,每个阵列的指向斗指针数组分配一个arbuckets,虽然不能说一元每增加需要一个指针,但实际情况可能更糟。这意味着元素,将一个54字节的数组,几乎一样,上面的估计。



从空间的角度来看,小数组的平均成本是大的。当然,大量的小数组不会被淹没在一个脚本中,它可以在很小的空间开销下编程,但是如果你把数组当作一个容器,它是一个不同的场景。实际应用中经常遇到的一个多维数组,并有很多的元素。例如,一个元素的一维数组消耗约10K 540k内存,和二维阵列理论10k x 10只需要6M左右的空间,但根据memory_get_usage结果比这更多,两次{ 10K,三维阵列5,2 }实际上消耗23m,阵列确实不小。



PHP数组内存利用率低的原因是,下面的文章将解释PHP数组操作的具体实现。



以上是本文的全部内容,希望能对您有所帮助,希望大家多多支持。