目录
PHP的垃圾回收机制详解
首页 后端开发 php教程 PHP的垃圾回收机制详解_PHP教程

PHP的垃圾回收机制详解_PHP教程

Jul 13, 2016 am 10:10 AM
垃圾 机制

PHP的垃圾回收机制详解

最近由于使用php编写了一个脚本,模拟实现了一个守护进程,因此需要深入理解php中的垃圾回收机制。本文参考了PHP手册。
 
在理解PHP垃圾回收机制(GC)之前,先了解一下变量的存储。
 
php中变量存在于一个zval的变量容器中。结构如下:
 
 
 
 
 
类型
 
 
is_ref
 
refcount
 
 
 
 
 
zval中,除了存储变量的类型和值之外,还有is_ref字段和refcount字段。
 
is_ref:是个bool值,用来区分变量是否属于引用集合。什么意思呢,你可以这么认为:表示变量是否有一个以上的别名。 
refcount:计数器,表示指向这个zval变量容器的变量个数。 
两者之间有这么一个默认关系:当refcount值为1时,is_ref的值为false。因为refcount为1,此变量不可能有多个别名,也就不存在引用了。
 
安装xdebug拓展之后,可以利用xdebug_debug_zval打印出zval容器详情。
 
这里有一点需要注意,将一个变量 = 赋值给另一个变量时,不会立即为新变量分配内存空间,而是在原变量的zval中给refcount加1。 只有当原变量或者发生改变时,才会为新变量分配内存空间,同时原变量的refcount减 1 。当然,如果unset原变量,新变量直接就使用原变量的zval而不是重新分配。
 
 &引用赋值时,原变量的is_ref 变为1,refcount 加1.  如果给一个变量&赋值,之前 = 赋值的变量会分配空间。
 
 
 
 
$a = 1;
xdebug_debug_zval('a');
echo PHP_EOL;
$b = $a;
xdebug_debug_zval('a');
echo PHP_EOL;
 
$c = &$a;
xdebug_debug_zval('a');
echo PHP_EOL;
 
xdebug_debug_zval('b');
echo PHP_EOL;
?>
  运行结果如下:
 
a:(refcount=1, is_ref=0),int 1
 
a:(refcount=2, is_ref=0),int 1
 
a:(refcount=2, is_ref=1),int 1
 
b:(refcount=1, is_ref=0),int 1
 
 
 
 
 
上面描述的zval存储的是标量,那复合类型的数组是如何存储的呢?
 
 
$a = array( 'meaning' => 'life', 'number' => 42 );
xdebug_debug_zval( 'a' );
echo PHP_EOL;
class Test{
    public $a = 1;
    public $b = 2;
     
    function handle(){
        echo 'hehe';
    }
}
 
$test = new Test();
xdebug_debug_zval('test');
?>
  运行结果如下:
 
a:(refcount=1, is_ref=0),
 
array
  'meaning' => (refcount=1, is_ref=0),
string
 
'life' (length=4)
  'number' => (refcount=1, is_ref=0),
int
 
 42
test:(refcount=1, is_ref=0),
 
object(Test)[1]
  public 'a' => (refcount=2, is_ref=0),
int
 
 1
  public 'b' => (refcount=2, is_ref=0),
int
 
2
 
可以看出,数组用了比数组长度多1个zval存储。对象类似。下面给出了数组的存储形象表示
 
 
 
可以看到:数组分配了三个zval容器:a   meaning  number
 
现在看看所谓的环状引用是如何生成的
 
 
$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );
?>
  运行结果:
 
a:(refcount=2, is_ref=1),
 
array
  0 => (refcount=1, is_ref=0),
string
 
 'one' (length=3)
  1 => (refcount=2, is_ref=1), &array
 
a 和 1 的zval容器 是一样的。如下:
 
 
 
 
 
 
 
这样就形成了环状引用。
 
在5.2及更早版本的PHP中,没有专门的垃圾回收器GC(Garbage Collection),引擎在判断一个变量空间是否能够被释放的时候是依据这个变量的zval的refcount的值,如果refcount为0,那么变量的空间可以被释放,否则就不释放,这是一种非常简单的GC实现。
 
现在unset ($a),那么array的refcount减1变为1.现在无任何变量指向这个zval,而且这个zval的计数器为1,不会回收。
 
 
 
 
 
尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),由于数组元素“1”仍然指向数组本身,所以这个容器不能被清除 。因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏。庆幸的是,php将在请求结束时清除这个数据结构,但是在php清除之前,将耗费不少空间的内存。如果你要实现分析算法,或者要做其他像一个子元素指向它的父元素这样的事情,这种情况就会经常发生。当然,同样的情况也会发生在对象上,实际上对象更有可能出现这种情况,因为对象总是隐式的被引用。
 
 
 
如果上面的情况发生仅仅一两次倒没什么,但是如果出现几千次,甚至几十万次的内存泄漏,这显然是个大问题。在长时间运行的脚本,比如请求基本上不会结束的守护进程时,就会出现问题,内存空间会不断耗费,导致内存不足而崩溃。
 
 
 
PHP5.3中,采用了专门的算法(比较复杂)。,来处理环状引用导致内存泄露的问题。
 
当一个zval可能为垃圾时,回收算法会把这个zval放入一个内存缓冲区。当缓冲区达到最大临界值时(最大值可以设置),回收算法会循环遍历所有缓冲区中的zval,判断其是否为垃圾,并进行释放处理。或者我们在脚本中使用gc_collect_cycles,强制回收缓冲区中的垃圾。
 
在php5.3的GC中,针对的垃圾做了如下说明:
 
1:如果一个zval的refcount增加,那么此zval还在使用,肯定不是垃圾,不会进入缓冲区
 
2:如果一个zval的refcount减少到0, 那么zval会被立即释放掉,不属于GC要处理的垃圾对象,不会进入缓冲区。
 
 3:如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾,将其放入缓冲区。PHP5.3中的GC针对的就是这种zval进行的处理。
 
 
 
 
 
开启/关闭垃圾回收机制可以通过修改php配置实现,也可以在程序中使用gc_enable() 和 gc_disable()开启和关闭。
 
 
 
开启垃圾回收机制后,针对内存泄露的情况,可以节省大量的内存空间,但是由于垃圾回收算法运行耗费时间,开启垃圾回收算法会增加脚本的执行时间。
 
下面是php手册中给的一个脚本
 
 
class Foo
{
    public $var = '3.1415962654';
}
 
$baseMemory = memory_get_usage();
 
for ( $i = 0; $i
{
    $a = new Foo;
    $a->self = $a;
    if ( $i % 500 === 0 )
    {
        echo sprintf( '%8d: ', $i ), memory_get_usage() - $baseMemory, "\n";
    }
}
?>
  
 
针对这个脚本,给出了其在php5.2和5.3中内存的占用情况,如下图:
 
 
 
针对下面这个脚本
 
 
class Foo
{
    public $var = '3.1415962654';
}
 
for ( $i = 0; $i
{
    $a = new Foo;
    $a->self = $a;
}
 
echo memory_get_peak_usage(), "\n";
?>
  
 
开启垃圾回收机制,相对于不开启的时候,脚本执行时间增加了7%
 
通常,PHP中的垃圾回收机制,仅仅在循环回收算法确实运行时会有时间消耗上的增加。但是在平常的(更小的)脚本中应根本就没有性能影响。
 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/938943.htmlTechArticlePHP的垃圾回收机制详解 最近由于使用php编写了一个脚本,模拟实现了一个守护进程,因此需要深入理解php中的垃圾回收机制。本文参考了...
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

深入探讨Golang变量的存储位置和机制 深入探讨Golang变量的存储位置和机制 Feb 28, 2024 pm 09:45 PM

标题:深入探讨Golang变量的存储位置和机制随着Go语言(Golang)在云计算、大数据和人工智能领域的应用逐渐增多,深入了解Golang变量的存储位置和机制变得尤为重要。在本文中,我们将详细探讨Golang中变量的内存分配、存储位置以及相关的机制。通过具体代码示例,帮助读者更好地理解Golang变量在内存中是如何存储和管理的。1.Golang变量的内存

深入了解CSS布局重新计算和渲染的机制 深入了解CSS布局重新计算和渲染的机制 Jan 26, 2024 am 09:11 AM

CSS回流(reflow)和重绘(repaint)是网页性能优化中非常重要的概念。在开发网页时,了解这两个概念的工作原理,可以帮助我们提高网页的响应速度和用户体验。本文将深入探讨CSS回流和重绘的机制,并提供具体的代码示例。一、CSS回流(reflow)是什么?当DOM结构中的元素发生可视性、尺寸或位置改变时,浏览器需要重新计算并应用CSS样式,然后重新布局

win10清理系统垃圾的步骤教程 win10清理系统垃圾的步骤教程 Jul 13, 2023 pm 09:53 PM

一些用户在使用电脑的时候,出现了win10系统清理垃圾的情况,当遇到win10系统清理垃圾这种情况,我们应该如何解决呢?如今还有很多用户不知道如何处理win10系统清理垃圾的情况,那么接下来就来看看win10清理系统垃圾的步骤教程,大家一起来看看吧。1、在电脑桌面上,点击“此电脑”,管理。2、选择磁盘管理3、选择你要清理的磁盘,右击选择属性。4、点击页面下方的“磁盘清理”按钮5、在出现的界面中,选择要清理的文件,点击“确定”,点击“删除文件”即可。以上就是win10清理系统垃圾的步骤教程啦,希望

PHP中的自动加载机制 PHP中的自动加载机制 Jun 18, 2023 pm 01:11 PM

随着PHP语言越来越受欢迎,开发人员需要使用越来越多的类和函数。当项目规模扩大时,手动引入所有依赖项将变得不切实际。这时候就需要一种自动加载机制来简化代码开发和维护过程。自动加载机制是一种PHP语言的特性,可以在运行时自动载入所需的类和接口,并减少手动的类文件引入。这样,程序员可以专注于开发代码,减少因繁琐的手动类引入而产生的错误和时间浪费。在PHP中,一般

如何在Go中使用错误处理机制? 如何在Go中使用错误处理机制? May 11, 2023 pm 04:45 PM

Go语言作为一门强类型、高效、现代化的编程语言,在现代软件开发中得到了越来越广泛的应用。其中,错误处理机制是Go语言值得关注的一个方面,而Go语言的错误处理机制相比于其他编程语言也有很大的不同和优越性。本文将介绍Go语言的错误处理机制的基本概念、实现方式以及最佳实践,以帮助读者更好地理解和使用Go语言中的错误处理机制。一、Go语言错误处理机制的基本概念在Go

PHP中的隐式转换机制解析 PHP中的隐式转换机制解析 Mar 09, 2024 am 08:00 AM

PHP中的隐式转换机制解析在PHP编程中,隐式转换是指在不显式指定类型转换的情况下,PHP自动将一个数据类型转换为另一个数据类型的过程。隐式转换机制在编程中非常常见,但也容易造成一些意想不到的bug,因此了解隐式转换机制的原理和规则对于编写稳健的PHP代码非常重要。1.整型与浮点型之间的隐式转换在PHP中,整型和浮点型之间的隐式转换是非常常见的。当一个整型

Go 语言中的内存管理机制是怎样的? Go 语言中的内存管理机制是怎样的? Jun 10, 2023 pm 04:04 PM

Go语言是一门广泛用于系统级编程的高效编程语言,其主要优势之一是其内存管理机制。Go语言内建的垃圾回收机制(GarbageCollection,简称GC)使得程序员不必亲自进行内存分配和释放操作,提高了开发效率和代码质量。本文将对Go语言中的内存管理机制进行详细介绍。一、Go内存分配在Go语言中,内存分配使用了两个堆区:小对象堆(small

win10怎么清理垃圾 教你怎么清理修复垃圾文件 win10怎么清理垃圾 教你怎么清理修复垃圾文件 Jan 12, 2024 am 08:18 AM

电脑使用时间久了C盘中的垃圾文件越来越来多,垃圾文件的存在会在一定程度上影响系统的运行速度,所以电脑使用的感觉会越来越慢,为了让电脑流畅运行,不影响正常的操作,下面,小编这就跟大家展示win10清理垃圾的操作。win10作为新系统,很多用户都已经安装了win10正式版,不过最近不少朋友反映自己安装了win10后系统盘变得过于拥挤了,导致运行系统的速度越来越慢,那么该如何去清理win10系统的垃圾呢?下面小编就给大家分享彻底清理win10系统的方法。win10怎么清理垃圾在Windows10桌面上

See all articles