①什么是内存泄漏?
描述:内存泄漏具有隐蔽、积累的特性,难检测,原因是内存块未被释放,属于遗漏型缺陷。极端情况会导致系统崩溃。
内存空间三部分:
程序存储区
静态存储区 存全局变量
动态存储区 存储变量
内存泄漏产生原因:开发中在动态存储区存变量,执行完无释放动态分配的存储空间造成内存泄漏。
而垃圾回收能在程序完成时及时释放内存,避免内存泄漏。对于PHP普通的网站是不需要垃圾回收,但如果是脚本长期运行就可能导致内存的泄漏,这时候垃圾回收机制的作用就发挥出来。
②PHP的垃圾回收
描述:
PHP5.2之前采用引用计数方式的内存动态管理,变量引用(refcount=0)时,PHP在内存中销毁该变量,而PHP在一个生命周期就会释放该进程。
循环引用如( $a = new A(); $a->self = $a;)而导致内存泄漏,引入了垃圾回收机制(就是说 PHP5.3开始引入垃圾回收机制)。变量容器zval也变动为如下:
struct _zval_struct {
/* Variable information */
zvalue_value value;/* value */
zend_uint refcount__gc;
zend_uchar type;/* active type */
zend_uchar is_ref__gc;
};
__gc 。
PHP5.3的垃圾回收算法:
该算法详细查看 http://docs.php.net/manual/zh/features.gc.collecting-cycles.php,以下简说:
PHP5.3的垃圾回收算法以计数为基础,分配一个固定大小的根缓冲区(默认存放10000个zval),并且将所有可能根(变量容器zval)放在缓冲区中,当缓冲区满时,对缓冲区内部所有不同的变量容器执行垃圾回收操作。
PHP5.3垃圾回收注意点:
1、只有 根缓冲区满后在开始垃圾回收。
2、可以解决 循环引用问题。
3、可以总将内存泄露保持在一个阈值以下。
PHP5.2与PHP5.3内存占用情况:
<?php
class Foo
{
public $var = '3.1415962654';
}
$baseMemory = memory_get_usage();
for ( $i = 0; $i <= 100000; $i++ )
{
$a = new Foo;
$a->self = $a;
if ( $i % 500 === 0 )
{
memory_get_usage() - $baseMemory, "\n";
}
}
参考:http://docs.php.net/manual/zh/features.gc.performance-considerations.php
http://www.jianshu.com/p/63a381a7f70c