一个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 相关文章推荐
Search Engine Friendly的URL设计
Oct 09 PHP
让PHP支持页面回退的两种方法
Jan 10 PHP
php 随机排序广告的实现代码
May 09 PHP
php URL跳转代码 减少外链
Jun 25 PHP
解析coreseek for sphinx的使用
Jun 21 PHP
yii框架表单模型使用及以数组形式提交表单数据示例
Apr 30 PHP
php实现根据url自动生成缩略图的方法
Sep 23 PHP
php中实现记住密码下次自动登录的例子
Nov 06 PHP
CodeIgniter多语言实现方法详解
Jan 20 PHP
php array_key_exists() 与 isset() 的区别
Oct 24 PHP
PHP addAttribute()函数讲解
Feb 03 PHP
php pdo连接数据库操作示例
Nov 18 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
DOTA2 探索永无止境 玩家自创强悍插眼攻略
2020/04/20 DOTA
最省空间的计数器
2006/10/09 PHP
php简单生成随机数的方法
2015/07/30 PHP
微信支付开发维权通知实例
2016/07/12 PHP
Laravel框架分页实现方法分析
2018/06/12 PHP
Laravel框架查询构造器简单示例
2019/05/08 PHP
比较详细的关于javascript中void(0)的具体含义解释
2007/08/02 Javascript
createTextRange()的使用示例含文本框选中部分文字内容
2014/02/24 Javascript
深入理解javascript严格模式(Strict Mode)
2014/11/28 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
2017/10/24 Javascript
Vuejs实现购物车功能
2017/11/05 Javascript
react+redux的升级版todoList的实现
2017/12/18 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
layui表单验证select下拉框实现验证的方法
2019/09/05 Javascript
ES6 class类链式继承,实例化及react super(props)原理详解
2020/02/15 Javascript
Vue组件模板的几种书写形式(3种)
2020/02/19 Javascript
vue 扩展现有组件的操作
2020/08/14 Javascript
[15:20]DOTA2亚洲邀请赛总决赛开幕式表演:羽泉献唱
2017/04/05 DOTA
跟老齐学Python之玩转字符串(1)
2014/09/14 Python
Python标准库defaultdict模块使用示例
2015/04/28 Python
python中尾递归用法实例详解
2015/04/28 Python
Python基于正则表达式实现检查文件内容的方法【文件检索】
2017/08/30 Python
python 寻找list中最大元素对应的索引方法
2018/06/28 Python
用python求一个数组的和与平均值的实现方法
2019/06/29 Python
python实现替换word中的关键文字(使用通配符)
2020/02/13 Python
CSS3径向渐变之大鱼吃小鱼之孤单的大鱼
2016/04/26 HTML / CSS
戴尔美国官网:Dell
2016/08/31 全球购物
Gina Bacconi官网:吉娜贝康尼连衣裙和礼服
2018/04/24 全球购物
SHEIN香港:价格实惠的女性时尚服装
2018/08/14 全球购物
雷蛇美国官网:Razer
2020/04/03 全球购物
什么是WEB控件?使用WEB控件有哪些优势?
2012/01/21 面试题
给民警的表扬信
2014/01/08 职场文书
前厅部经理岗位职责范文
2014/02/04 职场文书
安全生产标语
2014/06/06 职场文书
工程售后服务方案
2014/06/08 职场文书
销售员试用期自我评价
2014/09/15 职场文书