PHP垃圾回收

之前,被面试官问到性能,内存占用问题,我当时就蒙B了。没有接触呀,没有那么高的学问啊,开始担心自己会被刷下来。这样的事我看大家都遇到过吧。本次我们一起学学PHP垃圾回收,内存占用,同时解破面试官是如何装逼的

zval容器

列1.文件index.php,把下面这段代码copy到文件里

<?php
   $a = "hello world";
   xdebug_debug_zval('a');

结果

local_www $ php -f index.php 
a: (refcount=0, is_ref=0)='hello world'
local_www $

前提是要安装xdebug扩展,才能通过xdebug_debug_zval函数查看

通过上面的这个列子我们初步认识到,PHP变量是存放在一个zval的容器里,这个容器除了包含变了的类型和值外,还包含两个字节的额外信息(refcount,is_ref)。

refcount:用以表示指向这个zval变量容器的变量个数

is_ref:是个bool值,用来标识这个变量是否是属于引用集合

列2.在列1的基础上加入[Math Processing Error]b=a

<?php
   $a = "hello world";
   $b = $a;
   xdebug_debug_zval('a');

PHP5.6版本或者之前版本


local_www $ php -f index.php 
a: (refcount=2, is_ref=0)='hello world'
local_www $

PHP7.0版本

扫描二维码关注公众号,回复: 2277802 查看本文章

local_www $ php -f index.php 
a: (refcount=0, is_ref=0)='hello world'
local_www $

注意:refcount在这个容量的变数个数

通过上面的结果,我们可以猜测一下是不是PHP7.0版本a,b变量使用的是不同的容器呢?下面我们就用代码来证实这一点

<?php
   $a = "hello world";
   $b = $a;
   unset($a);
   xdebug_debug_zval('a');
   xdebug_debug_zval('b');

PHP5.6版本或者之前版本

$ php -f index.php 
b: (refcount=0, is_ref=0)='hello world'

PHP7.0版本

$ php -f index.php 
a: (refcount=0, is_ref=0)=*uninitialized*
b: (refcount=0, is_ref=0)='hello world'

接下来就是考虑这些容器什么时候释放呢?

清理变量容器问题

尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),由于数组元素“1”仍然指向数组本身,所以这个容器不能被清除 。因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏。庆幸的是,php将在脚本执行结束时清除这个数据结构,但是在php清除之前,将耗费不少内存。如果你要实现分析算法,或者要做其他像一个子元素指向它的父元素这样的事情,这种情况就会经常发生。当然,同样的情况也会发生在对象上,实际上对象更有可能出现这种情况,因为对象总是隐式的被引用。

如果上面的情况发生仅仅一两次倒没什么,但是如果出现几千次,甚至几十万次的内存泄漏,这显然是个大问题。这样的问题往往发生在长时间运行的脚本中,比如请求基本上不会结束的守护进程(deamons)或者单元测试中的大的套件(sets)中。后者的例子:在给巨大的eZ(一个知名的PHP Library) 组件库的模板组件做单元测试时,就可能会出现问题。有时测试可能需要耗用2GB的内存,而测试服务器很可能没有这么大的内存。

从PHP性能方面考虑的因素的文档中我们了解到PHP已经做了处理,也就是说没有我们的事情了,但如果你却是需要处理一下内存占用情况,也就是一个函数(gc_collect_cycles() )就可以帮你搞定。

总结

也就是说垃圾回收跟你没有半毛的关系。只要写的代码规模一些就OK了

猜你喜欢

转载自blog.csdn.net/phparchitect/article/details/81094337