php 浮点型-PHP内存消耗是C语言的两倍? 有用的是...

2023-08-26 0 778 百度已收录

PHP 源代码中的 zval

在 PHP 中定义变量不需要声明类型。 一开始,变量$a被赋予一个整数值,以后可以很容易地更改为其他类型

那么PHP源码中如何存储这个变量$a呢? 带着这个疑问,我们来看看PHP的源码

PHP的源代码是由C编译的,PHP源代码中使用了一个zval结构来存储PHP代码中创建的变量。 我们把zval结构体的定义拿出来简单分析一下。

这是 PHP 在 Github 上的官方仓库:github.com/php/php-src,本文使用的分支是 PHP-7.4.29。

zval结构

在PHP源码中找到这个文件:php-src/Zend/zend_types.h,可以看到zval结构体的定义如下,源码如右。

源码中使用了PHP自己定义的类型zend_uchar、uint16_t、uint32_t等,这个类型在平台和不同平台的编译器下会转换为charshorint。

为了便于理解,我将其翻译成通用类型php 浮点型,并显示在源码右侧。 同时还扩展了宏函数ZEND_ENDIAN_LOHI_3()。

typedef struct _zval_struct zval;...       《源代码》                                               《翻译后》-------------------------------------------------------------------------------------------struct _zval_struct {                               | struct _zval_struct {    zend_value value;                               |     zend_value value;    union {                                         |     union {        struct {                                    |         struct {            ZEND_ENDIAN_LOHI_3(                     |             unsigned char type;                zend_uchar type,                    |             unsigned char type_flags;                zend_uchar type_flags,              |             union {                union {                             |                 unsigned short extra;                    uint16_t extra;                 |             } u;                } u                                 |         } v;            )                                       |         unsigned int type_info;        } v;                                        |     } u1;        uint32_t type_info;                         |     union {    } u1;                                           |         unsigned int next;    union {                                         |         unsigned int cache_slot;        uint32_t next;                              |         unsigned int opline_num;        uint32_t cache_slot;                        |         unsigned int lineno;        uint32_t opline_num;                        |         unsigned int num_args;        uint32_t lineno;                            |         unsigned int fe_pos;        uint32_t num_args;                          |         unsigned int fe_iter_idx;        uint32_t fe_pos;                            |         unsigned int access_flags;        uint32_t fe_iter_idx;                       |         unsigned int property_guard;        uint32_t access_flags;                      |         unsigned int constant_flags;        uint32_t property_guard;                    |         unsigned int extra;        uint32_t constant_flags;                    |     } u2;        uint32_t extra;                             | };    } u2;                                           |};                                                 |

在zval结构中,变量的值存储在zend_value类型的value属性中。 并用u1.v.type来记录这个值的类型,例如IS_LONG对应整型,IS_STRING对应字符串类型。

zend_value 联合

zend_value类型也在php-src/Zend/zend_types.h中定义,它是一个联合体。 下面是zend_value union的定义,左边是源码。 同样在左侧,我也做了一个简单的翻译php 浮点型,将zend_longuint32_t翻译成常见的类型以供查看。

            《源代码》                                              《翻译后》------------------------------------------------------------------------------------typedef union _zend_value {                         | typedef union _zend_value {    zend_long         lval; /* long value */        |     long              lval;    double            dval; /* double value */      |     double            dval;    zend_refcounted  *counted;                      |     zend_refcounted  *counted;    zend_string      *str;                          |     zend_string      *str;    zend_array       *arr;                          |     zend_array       *arr;    zend_object      *obj;                          |     zend_object      *obj;    zend_resource    *res;                          |     zend_resource    *res;    zend_reference   *ref;                          |     zend_reference   *ref;    zend_ast_ref     *ast;                          |     zend_ast_ref     *ast;    zval             *zv;                           |     zval             *zv;    void             *ptr;                          |     void             *ptr;    zend_class_entry *ce;                           |     zend_class_entry *ce;    zend_function    *func;                         |     zend_function    *func;    struct {                                        |     struct {        uint32_t w1;                                |         unsigned int w1;        uint32_t w2;                                |         unsigned int w2;    } ww;                                           |     } ww;} zend_value;                                       | } zend_value;

union的一个特点是它占用的显存是其属性中最大的类型对应的厚度。

其中zend_long为long类型。 可以看到long类型的lval和double类型的dval占用的宽度都是8个字节。 上面其他指针类型也是8字节。 最后一个结构体属性ww由两个int类型组成,厚度相乘也是8个字节。

因此,该联合的厚度为 8 字节。

在我们编写的PHP代码中,整型和浮点型数据的值会直接存储在lval和dval中。

如果是字符串、数组或者其他类型,就会开辟一块空间来存储数据,并将其地址存储在zend_value中,即zval.value属性,如:zval.value.zend_long=9527,zval .value.zend_string=字符串地址,zval.value.zend_array=链表地址。

然后将zval.u1.v.type上的这个zval.value标记为整数,或者浮点,或者字符串,或者其他类型。

zval.u1.v.type类型定义也在php-src/Zend/zend_types.h文件中,所有定义如下:

/* regular data types */#define IS_UNDEF        0#define IS_NULL         1#define IS_FALSE        2#define IS_TRUE         3#define IS_LONG         4#define IS_DOUBLE       5#define IS_STRING       6#define IS_ARRAY        7#define IS_OBJECT       8#define IS_RESOURCE     9#define IS_REFERENCE    10/* constant expressions */#define IS_CONSTANT_AST 11/* internal types */#define IS_INDIRECT     13#define IS_PTR          14#define IS_ALIAS_PTR    15#define _IS_ERROR       15/* fake types used only for type hinting (Z_TYPE(zv) can not use them) */#define _IS_BOOL        16#define IS_CALLABLE     17#define IS_ITERABLE     18#define IS_VOID         19#define _IS_NUMBER      20

zval 结构的内存使用情况

接下来我们来分析一下zval所需的显存。

也就是说,当我们编写PHP代码时,如果创建一个整型变量,那么它在运行时实际上会占用16字节的显存,显存成本至少是C语言的两倍。 事实上,这两倍的成本也带来了PHP处理变量的灵活性。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 php php 浮点型-PHP内存消耗是C语言的两倍? 有用的是... https://www.wkzy.net/game/153995.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务