一个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 相关文章推荐
PHP 已经成熟
Dec 04 PHP
Dedecms V3.1 生成HTML速度的优化办法
Mar 18 PHP
asp和php下textarea提交大量数据发生丢失的解决方法
Jan 20 PHP
PHP FOR MYSQL 代码生成助手(根据Mysql里的字段自动生成类文件的)
Jul 23 PHP
批量去除PHP文件中bom的PHP代码
Mar 13 PHP
php5.3 注意事项说明
Jul 01 PHP
解析PHP 5.5 新特性
Jul 02 PHP
PHP图像处理之使用imagecolorallocate()函数设置颜色例子
Nov 19 PHP
php实现session自定义会话处理器的方法
Jan 27 PHP
php中文乱码问题的终极解决方案汇总
Aug 01 PHP
php静态成员方法和静态的成员属性的使用方法
Oct 26 PHP
PHP+百度AI OCR文字识别实现了图片的文字识别功能
May 08 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
php读取30天之内的根据算法排序的代码
2008/04/06 PHP
php 生成随机验证码图片代码
2010/02/08 PHP
PHP array_reverse() 函数原理及实例解析
2020/07/14 PHP
JS Timing
2007/04/21 Javascript
jQuery获取Select选择的Text和Value(详细汇总)
2013/01/25 Javascript
jquery中插件实现自动添加用户的具体代码
2013/11/15 Javascript
两个select多选模式的选项相互移动(示例代码)
2014/01/11 Javascript
AngularJS 使用 UI Router 实现表单向导
2016/01/29 Javascript
使用JQuery 加载页面时调用JS的实现方法
2016/05/30 Javascript
正则表达式替换html元素属性的方法
2016/11/26 Javascript
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
微信小程序实现的贪吃蛇游戏【附源码下载】
2018/01/03 Javascript
JavaScript变速动画函数封装添加任意多个属性
2019/04/03 Javascript
React Native中ScrollView组件轮播图与ListView渲染列表组件用法实例分析
2020/01/06 Javascript
[01:07:13]TNC vs Pain 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
python 从远程服务器下载东西的代码
2013/02/10 Python
Python批量修改文件后缀的方法
2014/01/26 Python
Python实现压缩和解压缩ZIP文件的方法分析
2017/09/28 Python
Python使用Matplotlib模块时坐标轴标题中文及各种特殊符号显示方法
2018/05/04 Python
python实现推箱子游戏
2020/03/25 Python
Python爬虫 scrapy框架爬取某招聘网存入mongodb解析
2019/07/31 Python
Python 音频生成器的实现示例
2019/12/24 Python
Python3搭建http服务器的实现代码
2020/02/11 Python
python使用pandas抽样训练数据中某个类别实例
2020/02/28 Python
python 通过邮件控制实现远程控制电脑操作
2020/03/16 Python
关于python的缩进规则的知识点详解
2020/06/22 Python
html5 canvas绘制放射性渐变色效果
2018/01/04 HTML / CSS
校园报刊亭的创业计划书
2014/01/02 职场文书
元旦联欢会感言
2014/03/04 职场文书
北京奥运会口号
2014/06/21 职场文书
领导班子四风表现材料
2014/08/23 职场文书
工资证明格式模板
2015/06/12 职场文书
2015入党自传格式范文
2015/06/26 职场文书
Nginx+Tomcat实现负载均衡、动静分离的原理解析
2021/03/31 Servers
一道JS算法面试题——冒泡、选择排序
2021/04/21 Javascript
nginx配置虚拟主机的详细步骤
2021/07/21 Servers