首页 / PHP / PHP7内存性能优化的思想精髓
PHP7内存性能优化的思想精髓
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了PHP7内存性能优化的思想精髓,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5755字,纯文字阅读大概需要9分钟。
内容图文
![PHP7内存性能优化的思想精髓](/upload/InfoBanner/zyjiaocheng/929/2620f3c65b7346ce953f146a0d3da47d.jpg)
2015年,PHP7的发布可以说是在技术圈里引起了不小的轰动,因为它的执行效率比PHP5直接翻了一倍。PHP7在内存方面,你是否知道作者都进行了哪些优化?几个核心结构体的改进只是表面上看起来优化的几个字节那么简单?让我们从几个核心的数据结构改进开始看起。
1PHP7 zval的变化1、php5.3中的zval:
typedef unsigned int zend_object_handle;
typedef struct _zend_object_value {
? ?zend_object_handle handle;
? ?zend_object_handlers *handlers;
} zend_object_value;
typedef union _zvalue_value {
? ?long lval; ? ? ? ? ? ? ? ? ?/* long value */
? ?double dval; ? ? ? ? ? ? ? ?/* double value */
? ?struct {
? ? ? ?char *val;
? ? ? ?int len;
? ?} str;
? ?HashTable *ht; ? ? ? ? ? ? ?/* hash table value */
? ?zend_object_value obj;
} zvalue_value;
struct _zval_struct {
? ?/* Variable information */
? ?zvalue_value value; ? ? /* value */
? ?zend_uint refcount__gc;
? ?zend_uchar type; ? ?/* active type */
? ?zend_uchar is_ref__gc;
};
我们这里只讨论64位操作系统下的情况。该zval_struct结构体中的由四个成员构成,其中zvalue_value稍微复杂一些,是一个联合体。联合体中最长的成员是一个指针加一个int,8+4=12字节。但是默认情况下,会进行内存对齐,故zval_struct会占用16字节。 那么。
_zval_struct总的字节 = value(16)+ refcount__gc(4)+ type(1)+ is_ref__gc(1)= 占用22字节。
最后再考虑下内存对齐,实际占用24字节。(如果算的有点晕话,感兴趣的同学可以写段简单的测试代码,使用sizeof查看一下)
2、PHP7.2中的zval
typedef struct _zval_struct ? ? zval;
typedef union _zend_value {
? ?zend_long ? ? ? ? lval; ? ? ? ? ? ? /* long value */
? ?double ? ? ? ? ? ?dval; ? ? ? ? ? ? /* double value */
? ?zend_refcounted ?*counted;
? ?zend_string ? ? ?*str;
? ?zend_array ? ? ? *arr;
? ?zend_object ? ? ?*obj;
? ?zend_resource ? ?*res;
? ?zend_reference ? *ref;
? ?zend_ast_ref ? ? *ast;
? ?zval ? ? ? ? ? ? *zv;
? ?void ? ? ? ? ? ? *ptr;
? ?zend_class_entry *ce;
? ?zend_function ? ?*func;
? ?struct {
? ? ? ?uint32_t w1;
? ? ? ?uint32_t w2;
? ?} ww;
} zend_value;
struct _zval_struct {
? ?zend_value ? ? ? ?value; ? ? ? ? ? ?/* value */
? ?union {
? ? ? ?struct {
? ? ? ? ? ?ZEND_ENDIAN_LOHI_4(
? ? ? ? ? ? ? ?zend_uchar ? ?type,
? ? ? ? ? ? ? ?zend_uchar ? ?type_flags,
? ? ? ? ? ? ? ?zend_uchar ? ?const_flags,
? ? ? ? ? ? ? ?zend_uchar ? ?reserved)
? ? ? ?} v;
? ? ? ?int type_info;
? ?} u1;
? ?union { ?...... } u2;
};
7.2中的zval_struct结构体里由3个成员构成,其中zend_value看起来比较复杂,实际上只是一个8字节的联合体。 u1也是一个联合体,占用是4个字节。u2也一样。这样zval_struct就实际占用16个字节。
2PHP7 HashTable的变化1、PHP5.3里的HashTable:
typedef struct _hashtable {
? ? ? ?uint nTableSize;
? ? ? ?uint nTableMask;
? ? ? ?uint nNumOfElements; ? //注意这里:浪费ing
? ? ? ?ulong nNextFreeElement;
? ? ? ?Bucket *pInternalPointer; ? ? ? /* Used for element traversal */
? ? ? ?Bucket *pListHead;
? ? ? ?Bucket *pListTail;
? ? ? ?Bucket **arBuckets;
? ? ? ?dtor_func_t pDestructor;
? ? ? ?zend_bool persistent;
? ? ? ?unsigned char nApplyCount;
? ? ? ?zend_bool bApplyProtection;
} HashTable;
在5.3里HashTable就是一个大struct, 有点小复杂,我们拆开了细说,
- uint nTableSize 4字节
uint nTableMask 4字节
uint nNumOfElements 4字节,
ulong nNextFreeElement 8字节 注意这前面的4个字节会被浪费掉,因为nNextFreeElement的开始地址需要对齐
Bucket *pInternalPointer 8字节
Bucket *pListHead 8字节
Bucket *pListTail 8字节
Bucket **arBuckets 8字节
dtor_func_t pDestructor 8字节
zend_bool persistent 1字节
unsigned char nApplyCoun 1字节
zend_bool bApplyProtection 1字节
最终,总字节数 = 4+4+4+4(nNextFreeElement前面这四个字节会留空)+8+8+8+8+8+8+1+1+1 = 67字节。再加上结构体本身要对齐到8的整数倍,所以实际占用72字节。
2、PHP7.2里的HashTable:
typedef struct _zend_array HashTable;
struct _zend_array {
? ?zend_refcounted_h gc;
? ?union {
? ? ? ?struct {
? ? ? ? ? ?ZEND_ENDIAN_LOHI_4(
? ? ? ? ? ? ? ?zend_uchar ? ?flags,
? ? ? ? ? ? ? ?zend_uchar ? ?nApplyCount,
? ? ? ? ? ? ? ?zend_uchar ? ?nIteratorsCount,
? ? ? ? ? ? ? ?zend_uchar ? ?consistency)
? ? ? ?} v;
? ? ? ?uint32_t flags;
? ?} u;
? ?uint32_t ? ? ? ? ?nTableMask;
? ?Bucket ? ? ? ? ? *arData;
? ?uint32_t ? ? ? ? ?nNumUsed;
? ?uint32_t ? ? ? ? ?nNumOfElements;
? ?uint32_t ? ? ? ? ?nTableSize;
? ?uint32_t ? ? ? ? ?nInternalPointer;
? ?zend_long ? ? ? ? nNextFreeElement;
? ?dtor_func_t ? ? ? pDestructor;
};s
在7.2里HashTable
- zend_refcounted_h gc 看起来唬人,实际就是个long,占用8字节
union... u 占用4字节
uint32_t 占用4字节
Bucket* 指针占用8字节
uint32_t nNumUsed 占用4字节
uint32_t nNumOfElements 占用4字节
uint32_t nTableSize 占用4字节
uint32_t nInternalPointer 占用4字节
zend_long nNextFreeElement 占用8字节
dtor_func_t pDestructor 占用8字节
总占用字节数 = 8+4+4+8+4+4+4+4+8+8 = 56字节,并且正好达到了内存对齐的状态,没有额外的浪费。
另外还有PHP源代码里经常出镜的Buckets也从72下降到了32字节,这里我就不翻源代码了。
3优化思想精髓当当当,敲黑板,重点来了!我们看了两个核心数据结构的结构体变化,这上面的优化都是什么含义呢? 拿HashTable举例,貌似从72字节优化到了56字节,这内存节约的也不是特别多嘛,才20%多而已!但这中间其实隐藏了两个较深层次优化思路:
第一、你是否记得我们前面CPU在向内存要数据的时候是以Cache Line为单位进行的,而我们说过Cache Line的大小就是64字节。回过头来看HashTable,在7.2里的56字节,只需要CPU向内存进行一次Cache Line大小的burst IO,就够了。而在5.3里的72字节,虽然只比Cache Line大了那么一丢丢,但是对不起,必须得进行两次burst IO才可以。 所以,在计算机里,56字节相对72字节实际上是翻倍的性能提升!!
第二、CPU的L1、L2、L3的容量是固定的几十K或者几十M。假设Cache的都是HashTable,那么Cache容量不变的条件下,能Cache住的HashTable将会翻倍,缓存命中率提升一大截。要知道L1命中后只需要1ns多一点的耗时,而如果穿透到内存的话可能就需要40多纳秒的延时了,整整差了几十倍。
所以PHP内核的作者大牛深谙CPU与内存的工作原理,表面上看起来只是几个字节的节约,但是实际上爆发出了巨大的性能提升!!
内容总结
以上是互联网集市为您收集整理的PHP7内存性能优化的思想精髓全部内容,希望文章能够帮你解决PHP7内存性能优化的思想精髓所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。