王志广的个人分享

PHP底层分析

admin发表于2014-12-29  4,085次浏览 标签: 

1、php特点
php虽然是脚本语言但是不是解释器解析的,而是zend虚拟机解析,php代码被编译成opcode,最后又由zend虚拟机来执行,执行完后opcode被清除(可以适用三方工具缓存opcode如apc、xcache,php不支持)

 

2、变量的实现
了解变量实现首先了解zend zvalue_value结构体
{
zvalue_value:[联合体] ,联合体的内容可能是C语言中的long,double,hashtable…
type:变量类型 , IS_NULL,IS_BOOL,IS_STRING…… IS_RESOURCE
refcount_gc:被指个数
is_ref_gc:是否引用
}
type字段的值为以下常量
IS_NULL, IS_BOOL,IS_LONG,IS_DOUBLE
IS_STRING,IS_ARRAY,IS_OBJECT
IS_RESOURCE
例如:
{
value:{char:’test’,len:5}
type:IS_STRING
refcount_gc:1
is_ref_gc:0
}
如果变量值是字符串,长度是已经缓存在联合体中的,所以strlen计算字符串长度很快

3、了解符号表和变量的花名册
变量符号表是存在hash表中,同时存的还有zvalue_value结构体的地址
在 hash symbol_table中

4、传值变化
传值变化只是改动了结构体中的refcount_gc:值
$a=3;这个时候只有$a指向这个结构体
{zvalue:3;type:IS_LONG;refcount_gc:1;is_ref_gc:0;}
$b=$a;这个时候$a和$b同时指向这个结构体
{zvalue:3;type:IS_LONG;refcount_gc:2;is_ref_gc:0;}
只有当$a或者$b修改时,结构体才分裂

5、引用赋值
引用变化是改动了结构体中的refcount_gc:值和is_ref_gc值
$a=3;这个时候只有$a指向这个结构体
{value:3;type:IS_LONG;refcount_gc:1;is_ref_gc:0;}
$b=&$a;这个时候$a和$b同时指向这个结构体
{value:3;type:IS_LONG;refcount_gc:2;is_ref_gc:1;}
当$a或者$b修改时结构体不分裂,值相应都变化

6、强制分裂
$a = 1;
$b = $a;
$c = &$a;
$c = 2;
如果is_ref_gc:0变为is_ref_gc:1的时候,recout_gc>1的时候,就会产生强制分裂,所有在$c=&$a;的时候,$a和$b就会分裂成俩个结构体

7、引用数组怪现象
$arr = array(1,2,3);
$v = &$arr[1];
$arrs = $arr;
$arr[1] = 100;
echo $arrs[1];//100
php对数组如果只修改数组内的元素,php没有产生强制分裂,反而是影响到,说明php没有检索php数组内的变量变化

8、循环怪现象
current(数组);
$arr = array(“a”,”b”,”c”,”d”);
foreach($arr as &$val){}
foreach($arr as $val){
print_R($arr);
}
//abca,abcb,abcc,abcc
这个时候产生的结果很是让人怀疑,其实这和引用数组怪象一样只不是变成了foreach形式
$val = &$arr[0];
$val = &$arr[1];
$val = &$arr[2];
$val = &$arr[3];
这样就是$val = &$arr[3]发生了应用

9、函数符号表与作用域
在php函数执行的时候,会生成环境执行体op_array(函数的执行步骤),不管函数执行多少次,op_array只存在一个,变量则存在*symbor_table(会生成对应环境栈 多个),所以函数内部变量不会影响外部变量,同时外部变量也不能影响内部变量

10、函数静态变量的实现
静态变量是放在op_array中所以不管调用多少次都是调用的一个静态变量。

11、常量
常量分系统定义和用户定义,所以用户定义和系统定义的重复,也不会产生错误
常量存储和变量差不多,不过常量的哈希表只有一个zend_constants所以对全局有效,而函数中的变量,则会生成一个独立的符号表,所以互不影响(不同文件变量是相互不影响的)
变量存储对象的时候,是走了 _toString()魔术方法函数转话
class test{
public $a = “test”;
public function _toString(){
return $this->name;
}
}
$b = new test();
define(‘c’,$b);
echo c;//test;

12、对象
对象只存储了对象名和对象池指针。对象在对象池中
handle指向hash表,然后hash表指向对象池

13、内存分析
php分为zend_mm_storge层、zend_mm_heap层、emalloc,efree层。
zend_mm_storge是php运行时会申请一块内存。
zend_mm_heap是在大块内存中在分层。
然后具体使用是emalloc,efree层,同时php有内存回收极致,当emalloc,efree层适用后,内存会在释放回到大层缓存中。

14、性能分析
使用XHProf查找PHP性能瓶颈

总结,php使用了大量的hash表,同时对应内存管理十分高效。

HHVM

你可以发表评论引用到你的网站或博客,或通过RSS 2.0订阅这个日志的所有评论。
上一篇:
下一篇:
已有2条评论
瓜丢网
2015 年 1 月 19 日

有点教程的味道

免费黑客网
2015 年 2 月 16 日

好深奥

我来说两句

  Ctrl+Enter