一个PHP数组应该有多大的分析


Posted in PHP onJuly 30, 2009

虽然通常在PHP中进行大量数组运算从一定程度上反应程序设计上可能存在问题,但是粗略的估计数组占用的内存是很有必要的。
首先感觉一下1000个元素的整数数组占有的内存:

echo memory_get_usage() . “\n”; 
$a = Array(); 
for ($i=0; $i<1000; $i++) { 
$a[$i] = $i + $i; 
} 
echo memory_get_usage() . “\n”; 
for ($i=1000; $i<2000; $i++) { 
$a[$i] = $i + $i; 
} 
echo memory_get_usage() . “\n”;

输出是:
58176
162956
267088
大 约可以知道 1000 个元素的整数数组需要占用 100k 内存,平均每个元素占用 100 个字节。而纯 C 中整体只需要 4k。memory_get_usage() 返回的结果并不是全是被数组占用了,还要包括一些 PHP 运行本身分配的一些结构,可能用内置函数生成的数组更接近真实的空间:
echo “init mem: ” . memory_get_usage() . “\n”; 
$a = array_fill(0, 10000, 1); 
echo “10k elements: ” . memory_get_usage() . “, system: ” . memory_get_usage(true) . “\n”; 
$b = array_fill(0, 10000, 1); 
echo “10k elements: ” . memory_get_usage() . “, system: ” . memory_get_usage(true) . “\n”;

得到:
init mem: 58468
10k elements: 724696, system: 786432
10k elements: 1390464, system: 1572864
从这个结果来看似乎一个数组元素大约只占用了 60 个左右的字节。再看看数组的C结构,PHP 中的数组变量,首先需要一个 zval 结构:
struct _zval_struct { 
zvalue_value value; 
zend_uint refcount__gc; 
zend_uchar type; 
zend_uchar is_ref__gc; 
};

zvalue_value 是一个union:
typedef union _zvalue_value { 
long lval; 
double dval; 
struct { 
char *val; 
int len; 
} str; 
HashTable *ht; 
zend_object_value obj; 
} zvalue_value;

通常 zval 结构需要 8+6=14 个字节,PHP中每个变量都有对应的 zval,但是数组,字符串和对象还需要另外的存储结构,而数组则是一个 HashTable :
typedef struct _hashtable { 
uint nTableSize; 
uint nTableMask; 
uint nNumOfElements; 
ulong nNextFreeElement; 
Bucket *pInternalPointer; 
Bucket *pListHead; 
Bucket *pListTail; 
Bucket **arBuckets; 
dtor_func_t pDestructor; 
zend_bool persistent; 
unsigned char nApplyCount; 
zend_bool bApplyProtection; 
} HashTable;

HashTable 结构需要 40 个字节,每个数组元素存储在 Bucket 结构中:
typedef struct bucket { 
ulong h; 
uint nKeyLength; 
void *pData; 
void *pDataPtr; 
struct bucket *pListNext; 
struct bucket *pListLast; 
struct bucket *pNext; 
struct bucket *pLast; 
char arKey[1]; 
} Bucket;

Bucket 结构需要 36 个字节,键长超过四个字节的部分附加在 Bucket 后面,而元素值很可能是一个 zval 结构,另外每个数组会分配一个由 arBuckets 指向的 Bucket 指针数组, 虽然不能说每增加一个元素就需要一个指针,但是实际情况可能更糟。这么算来一个数组元素就会占用 54 个字节,与上面的估算相差不远。
一个空数组至少会占用 14(zval) + 40(HashTable) + 32(arBuckets) = 86 个字节,作为一个变量应该在符号表中有个位置,也是一个数组元素,因此一个空数组变量需要 118 个字节来描述和存储。从空间的角度来看,小型数组平均代价较大,当然一个脚本中不会充斥数量很大的小型数组,可以以较小的空间代价来获取编程上的快捷。
但如果将数组当作容器来使用就是另一番景象了,实际应用经常会遇到多维数组,而且元素居多。比如10k个元素的一维数组大概消耗540k内存,而10k x 10 的二维数组理论上只需要 6M 左右的空间,但是按照 memory_get_usage 的结果则两倍于此,[10k,5,2]的三维数组居然消耗了23M,小型数组果然是划不来的。
PHP 相关文章推荐
phpmyadmin 访问被拒绝的真实原因
Jun 15 PHP
淘宝ip地址查询类分享(利用淘宝ip库)
Jan 07 PHP
php生成随机字符串可指定纯数字、纯字母或者混合的
Apr 18 PHP
destoon切换城市后实现logo旁边显示地区名称的方法
Aug 21 PHP
php实现的Timer页面运行时间监测类
Sep 24 PHP
php定时执行任务设置详解
Feb 06 PHP
PHP指定截取字符串中的中英文或数字字符的实例分享
Mar 18 PHP
PHP转换文本框内容为HTML格式的方法
Jul 20 PHP
详谈PHP中的密码安全性Password Hashing
Feb 04 PHP
Yii 2.0如何使用页面缓存方法示例
May 23 PHP
在Laravel 的 Blade 模版中实现定义变量
Oct 14 PHP
PHP中的输出echo、print、printf、sprintf、print_r和var_dump的示例代码
Dec 01 PHP
PHP UTF8编码内的繁简转换类
Jul 20 #PHP
php 验证码制作(网树注释思想)
Jul 20 #PHP
php PDO中文乱码解决办法
Jul 20 #PHP
PHP 配置文件中open_basedir选项作用
Jul 19 #PHP
PHP form 表单传参明细研究
Jul 17 #PHP
php与php MySQL 之间的关系
Jul 17 #PHP
php 图片上传类代码
Jul 17 #PHP
You might like
phpmyadmin 访问被拒绝的真实原因
2009/06/15 PHP
php获取本周开始日期和结束日期的方法
2015/03/09 PHP
PHP购物车类Cart.class.php定义与用法示例
2016/07/20 PHP
php+redis实现商城秒杀功能
2020/11/19 PHP
Javascript数组的排序 sort()方法和reverse()方法
2012/06/04 Javascript
选择器中含有空格在使用示例及注意事项
2013/07/31 Javascript
php is_numberic函数造成的SQL注入漏洞
2014/03/10 Javascript
JavaScript AJAX之惰性载入函数
2014/08/27 Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
2017/02/19 Javascript
nodejs爬虫遇到的乱码问题汇总
2017/04/07 NodeJs
node.js中express-session配置项详解
2017/05/31 Javascript
JavaScript实现body内任意节点的自定义属性功能示例
2017/09/18 Javascript
VueJS事件处理器v-on的使用方法
2017/09/27 Javascript
对angularjs框架下controller间的传值方法详解
2018/10/08 Javascript
对 Vue-Router 进行单元测试的方法
2018/11/05 Javascript
详解从react转职到vue开发的项目准备
2019/01/14 Javascript
JS使用栈判断给定字符串是否是回文算法示例
2019/03/04 Javascript
vue项目中实现缓存的最佳方案详解
2019/07/11 Javascript
js实现轮播图效果 z-index实现轮播图
2020/01/17 Javascript
使用Python操作Elasticsearch数据索引的教程
2015/04/08 Python
基于python操作ES实例详解
2019/11/16 Python
使用Python的Turtle库绘制森林的实例
2019/12/18 Python
吃透移动端 Html5 响应式布局
2019/12/16 HTML / CSS
UGG澳洲官网:UGG Australia
2018/04/26 全球购物
Flesh Beauty官网:露华浓集团旗下彩妆品牌
2021/02/15 全球购物
企业安全生产责任书范本
2014/07/28 职场文书
师德标兵事迹材料
2014/12/19 职场文书
表扬通报怎么写
2015/01/16 职场文书
小学感恩节活动总结
2015/03/24 职场文书
领导激励员工的演讲稿,各种会上用得到,建议收藏
2019/08/13 职场文书
英文诗歌翻译方法(赏析)
2019/08/16 职场文书
2019年感恩励志演讲稿(收藏备用)
2019/09/11 职场文书
使用nginx动态转换图片大小生成缩略图
2021/03/31 Servers
SQL Server——索引+基于单表的数据插入与简单查询【1】
2021/04/05 SQL Server
Python函数中的不定长参数相关知识总结
2021/06/24 Python
一篇文章看懂MySQL主从复制与读写分离
2021/11/07 MySQL