PHP引用计数器与写时复制

  • 2016-07-21
  • 1149
  • 1

之前在看《php核心技术与最佳实践》一书时,便了解到php的垃圾回收机制,文中提到的技术就是引用计数器和写时复制,这是php内核的一个优化手段,现做个简单整理。

众所周知,php与c++不同,它是不支持指针的,所以如果希望两个变量同时指向同一内存块怎么办呢?

由于这个问题,才产生了引用计数器和写时复制机制。

首先了解下php变量在php内核中是以zval结构的实体存在的,称为zval容器。php语言层中创建一个变量就会相应的在内核中创建zval容器。

zval容器有两个成员变量:

is_ref: bool值,标识变量是否是引用集合,即是不是用户使用 & 的强制引用。

refcount: 计算指向引用集合的变量个数。即用于标识此zval被多少个变量引用,即COW的自动引用,为0时会被销毁。

相关例子:

此时输出的结果为:

以上发现当$a=1 时 refcount=1 ,is_ref=0,这不难理解。但是当$b = $a; 即$a赋值给$b时,refount=2。

另外,当$b的变量又改变了之后,$a的refount又变回了1。

这便是写时复制机制在发生作用了。为了利于内存的复用,当一个变量赋值给另一个变量时,此时php内核都会使其指向同一个内存块(此时refcount=2或更多)。起到节约内存的作用,这对于产生大数组变量时尤为明显。当赋值之后的变量值又做修改时,此时因为两者不相等,所以又会重新指向一个新的内存块,原来的$a的refount又会变成1。实际上可以理解为,写时复制也是一种引用,只不过引用会随着变量值的改变而破坏罢了。

 

引用的相关例子:

此时输出的结果为:

可以看到,当$a引用赋值给$b时,此时$a的is_ref=1 ,说明此时用了引用。因采用了引用,当$b变量值改变之后,$a的refount还是2,即他们还是同时指向同一个zval容器,使用同一个内存块。

 


上一篇:  下一篇:

评论

  • 我是谁回复

    能发言?

Copyright © 2014-2016 lxlxw All Right Reserved