一个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下MAIL的另一解决方案
Oct 09 PHP
php中实现记住密码自动登录的代码
Mar 02 PHP
php图片加水印原理(超简单的实例代码)
Jan 18 PHP
php xml常用函数的集合(比较详细)
Jun 06 PHP
浅析51个PHP处理字符串的函数
Aug 02 PHP
简单谈谈php中ob_flush和flush的区别
Nov 27 PHP
php+jQuery+Ajax实现点赞效果的方法(附源码下载)
Jul 21 PHP
php构造方法中析构方法在继承中的表现
Apr 12 PHP
Yii2表单事件之Ajax提交实现方法
May 04 PHP
简单实用的PHP文本缓存类实例
Mar 22 PHP
php实现的简单多进程服务器类完整示例
Feb 01 PHP
yii框架结合charjs统计上一年与当前年数据的方法示例
Apr 04 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 分页类(模仿google)-面试题目解答
2009/09/13 PHP
php中隐形字符65279(utf-8的BOM头)问题
2014/08/16 PHP
php JWT在web端中的使用方法教程
2018/09/06 PHP
yii框架数据库关联查询操作示例
2019/10/14 PHP
JavaScript初学者需要了解10个小技巧
2010/08/25 Javascript
javascript定时保存表单数据的代码
2011/03/17 Javascript
DOM2非标准但却支持很好的几个属性小结
2012/01/21 Javascript
使用jQuery validate 验证注册表单实例演示
2013/03/25 Javascript
省市选择的简单实现(基于zepto.js)
2016/06/21 Javascript
一个非常好用的文字滚动的案例,鼠标悬浮可暂停[两种方案任选]
2016/12/01 Javascript
JavaScript版经典游戏之扫雷游戏完整示例【附demo源码下载】
2016/12/12 Javascript
javascript表单正则应用
2017/02/04 Javascript
AngularJS 防止页面闪烁的方法
2017/03/09 Javascript
微信小程序全局变量改变监听的实现方法
2019/07/15 Javascript
VUE.CLI4.0配置多页面入口的实现
2019/11/25 Javascript
vue使用微信扫一扫功能的实现代码
2020/04/11 Javascript
[47:04]LGD vs infamous Supermajor小组赛D组 BO3 第二场 6.3
2018/06/04 DOTA
Python中运算符&quot;==&quot;和&quot;is&quot;的详解
2016/10/08 Python
Python实现爬取马云的微博功能示例
2019/02/16 Python
python实现矩阵和array数组之间的转换
2019/11/29 Python
Python第三方包PrettyTable安装及用法解析
2020/07/08 Python
python 写一个文件分发小程序
2020/12/05 Python
python中的插入排序的简单用法
2021/01/19 Python
HTML+CSS+JavaScript实现图片3D展览的示例代码
2020/10/12 HTML / CSS
TobyDeals美国:在电子产品上获得最好的优惠和折扣
2019/08/11 全球购物
美国沙龙美发产品购物网站:Hair.com by L’Oreal
2020/11/09 全球购物
咖啡厅创业计划书范本
2014/01/22 职场文书
本科毕业生求职自荐信
2014/04/09 职场文书
爱岗敬业演讲稿
2014/05/05 职场文书
2014年工程师工作总结
2014/11/25 职场文书
地雷战观后感
2015/06/09 职场文书
色戒观后感
2015/06/12 职场文书
如何用 Python 子进程关闭 Excel 自动化中的弹窗
2021/05/07 Python
MongoDB安装使用并实现Python操作数据库
2021/06/28 MongoDB
Centos系统通过Docker安装并搭建MongoDB数据库
2022/04/12 MongoDB
Python绘制散点图之可视化神器pyecharts
2022/07/07 Python