PHP变量方式输出身高体重,PHP变量的CV类型

PHP变量的CV类型

在我们使用VLD扩展查看PHP生成的中间代码时,经常会看到有这样一项:compiled vars: !0 = $a,或者如果使用更加详细的 -dvld.verbosity=3参数,会看到IS_CV,IS_VAR等类型。这里所说的Compiled vars和IS_CV都与今天我们所要了解的CV类型有莫大的关系。

CV者,Compiled variable也。

CV类型是PHP编译过程中产生的一种变量类型,以类似于缓存的方式,提高某些变量的存储速度。

与CV类型同一级别的类型还有:

#define IS_CONST (1<<0)

#define IS_TMP_VAR (1<<1)

#define IS_VAR (1<<2)

#define IS_UNUSED (1<<3) /* Unused variable */

#define IS_CV (1<<4) /* Compiled variable */

比如最常见的赋值语句:$a = 10;

以php -dvld.active=1 -dvld.verbosity=3 test.php(这段代码在放在test.php文件中)查看。

function name: (null)

number of ops: 3

compiled vars: !0 = $a

line # * op return operands

----------------------------------------------

2 0 > EXT_STMT RES[ IS_UNUSED ] OP1[ IS_UNUSED ] OP2[ IS_UNUSED ]

1 ASSIGN OP1[IS_CV !0 ] OP2[ , IS_CONST (0) 10 ]

13 2 > RETURN OP1[IS_CONST (0) 1 ]

如上我们可以知道10的类型为IS_CONST,$a的类型为IS_CV。

这里的CV类型在代码运行时存储在哪呢?在什么时候能起到性能优化的作用?

我们知道PHP中间代码运行的数据大部分都放在全局变量execute_data中,对于这个变量我们通常以EX(element)的方式调用,如EX(CVs)、EX(opline)等等。通过对execute_data所有字段的查阅我们可以大概知道CV类型变量存放在EX(CVs)中。

如何判别呢?

同样,以上面的简单赋值语句为例,依据其中间代码(ZEND_ASSIGN),操作数的类型(IS_CV和IS_CONST),可以得出其中间代码最终执行的函数为:ZEND_ASSIGN_SPEC_CV_CONST_HANDLE。在此函数中,对于操作数据处理:

zval *value = &opline->op2.u.constant;

zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);

op2为右值,op1为左值,左值的查找处理是_get_zval_ptr_ptr_cv。如下:

static zend_always_inline zval **_get_zval_ptr_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)

{

zval ***ptr = &CV_OF(node->u.var);

if (UNEXPECTED(*ptr == NULL)) {

return _get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);

}

return *ptr;

}

// 函数中的CV_OF宏定义

#define CV_OF(i) (EG(current_execute_data)->CVs[i])

上面的函数和宏定义道出了CV这个类缓存机制的实现过程和CV类型的存储位置。

在函数中,程序会先判断变量是否存在于EX(CVs) – 这就是存储位置,如果存在则直接返回,否则调用_get_zval_cv_lookup,通过HashTable操作在EG(active_symbol_table)表中查找变量。虽然HashTable的查找操作已经比较快了,但是与原始的数组操作相比还是不在一个数量级。这就是CV类型变量的性能优化点所在。

以上是变量的赋值操作,也是变量的创建过程,与此对应,在变量销毁时PHP内核应该会对此种类型的变量执行清除HashTable和数组两个操作,以unset操作为例,针对IS_CV类型的变量,其中间代码最终会执行ZEND_UNSET_VAR_SPEC_CV_HANDLER。在此函数中不管是ZEND_QUICK_SET类型的操作,还是常规的unset操作,都会对HashTable(EG(active_symbol_table)或target_symbol_table)和数组(EX(CVs)和ex->CVs)执行清除操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值