首页 > 编程知识 正文

php堆和栈的区别,php垃圾

时间:2023-05-06 19:24:53 阅读:163849 作者:2631

介绍一下PHP的垃圾回收机制php使用引用计数(reference counting ) GC机制,同时使用根缓冲区机制,当PHP发现具有循环引用的zval时,将其放入根缓冲区中,并进行路由

1 .如果引用计数减少到零,则清除(free )所属的变量容器,如果不属于垃圾的2 .一个zval的引用计数减少但大于0,则其进入垃圾周期。 然后,在一个垃圾循环中,通过检查引用计数是否减少1,检查哪个变量容器的引用次数为0,发现哪些部分是垃圾。 每个对象都包含引用计数器refcount,每个引用连接到一个对象,并对计数器加1。 如果reference离开生存空间或设置为NULL,计数器将减1。 当一个对象的引用计数器为零时,PHP知道你不再需要使用这个对象,并释放它占用的内存空间。

下列关于PHP垃圾回收的说法,错误的是?A,垃圾收集的开启/关闭机制可以通过变更php结构来实现

b、可以通过程序使用gc_enable (和gc_disable )打开和关闭。

C、PHP的垃圾回收机制,大大提高了系统的性能。

d .打开垃圾回收机制可以为内存泄漏节省大量的内存空间,但由于垃圾回收算法的执行需要时间,所以打开垃圾回收算法会增加脚本的执行时间。

参考答案:C

答: PHP中的垃圾回收机制,只有在循环回收算法确实执行时,时间消耗才会增加。 但是,普通(更小)脚本应该对性能没有任何影响。

php垃圾回收机制的说法错误的是?A,在垃圾循环中,通过检查参照计数是否减少了1,以及哪个变量容器的参照次数为零,来发现哪个部分是垃圾

b,gc_enable ()和gc_disable () )的函数,可以打开和关闭垃圾回收机制

c .通过清理未使用的变量节省内存消耗

d、php代码运行时会自动执行垃圾回收,因此不需要手动执行垃圾回收

参考答案:D

问题解决: php代码可能长时间运行,但其间存在未被引用的变量会消耗内存空间、运行缓慢等问题知识篇一、概念

垃圾回收是许多编程语言中都有的内存管理机制。 与非托管语言相反,C、C和Objective C是具有GC机制的语言,用户必须手动收集内存。 Java、javaScript和PHP可以自动管理内存。 垃圾回收机构(gc )顾名思义就是废弃物的再利用,是动态的存储分配方案。 程序不再需要的已分配内存块将自动释放。 垃圾回收机制使程序员不必太在意程序的内存分配,而可以集中精力处理业务逻辑。

在当前流行的各种语言中,垃圾收集机制是新一代语言的共同特征,如Python、PHP、C#、Ruby等都使用了垃圾收集机制。

二、PHP垃圾回收机制

1、在PHP 5.3版之前,垃圾回收机制是单纯的“引用计数”。

什么叫做引用计数?

因为PHP是用c写的,所以c中有被称为结构体的东西,我们PHP的变量是这样被容纳在c中的。

每个PHP变量都存在于一个名为zval的容器中,zval容器除了变量名称和值之外还包含两个字节的附加信息。

一个称为is_ref '的布尔值,指示此变量是否属于引用集合。 通过这个字节,我们php可以区分普通变量和参考变量。

第二个额外的字节是“refcount”,表示指向此容器的变量的数量。 也就是说:

对每个存储器对象分配计数器,存储器对象被变量引用时,计数器1;

变量参照被删除后(unset ) )执行后),计数器-1;

计数器=0时,未使用内存对象,丢弃该内存对象,完成垃圾回收。

然后,在一个生命周期结束时,PHP将释放此进程/线程所占用的内容。 这种方式决定了PHP前期不太需要考虑内存泄漏问题。

但是,如果多个对象相互引用成环状,则内存对象的计数器不会减少到0。 此时,此组内存对象尚未使用,但无法重用,并且会发生内存泄漏。

从php5.3开始,使用新的垃圾回收机制,实现了基于引用计数检测内存对象中引用循环的存在性和避免内存泄漏的复杂算法。

2、随着PHP的发展,PHP开发人员的增加和其承载的业务范围的扩大,PHP5.3引入了更完善的垃圾回收机制,新的垃圾回收机制解决了无法应对循环的引用内存泄漏问题。 根据官方文档,每个php变量都存在于名为' zval '的变量容器中。 zval变量容器,除了变量类型和值外,还包含2字节附加信息。 第一个是' is_ref ',它是标识此变量是否属于引用集合(refe )的bool值

rence set)。通过这个字节,php引擎才能把普通变量和引用变量区分开来,由于php允许用户通过使用&来使用自定义引用,zval变量容器中还有一个内部引用计数机制,来优化内存使用。

第二个额外字节是"refcount",用以表示指向这个zval变量容器的变量(也称符号即symbol)个数。所有的符号存在一个符号表中,其中每个符号都有作用域(scope)。

官方文档所说,可以使用Xdebug来检查引用计数情况:

<?php$a = "new string";$c = $b = $a;xdebug_debug_zval( 'a' );unset( $b, $c );xdebug_debug_zval( 'a' );?>

 

以上例程会输出:

a: (refcount=3, is_ref=0)='new string'a: (refcount=1, is_ref=0)='new string'

注意:从PHP7的NTS版本开始,以上例程的引用将不再被计数,即$c=$b=$a之后a的引用计数也是1.具体分类如下:

在PHP 7中,zval可以被引用计数或不被引用。在zval结构中有一个标志确定了这一点。

① 对于null,bool,int和double的类型变量,refcount永远不会计数;

② 对于对象、资源类型,refcount计数和php5的一致;

③ 对于字符串,未被引用的变量被称为“实际字符串”。而那些被引用的字符串被重复删除(即只有一个带有特定内容的被插入的字符串)并保证在请求的整个持续时间内存在,所以不需要为它们使用引用计数;如果使用了opcache,这些字符串将存在于共享内存中,在这种情况下,您不能使用引用计数(因为我们的引用计数机制是非原子的);

④对于数组,未引用的变量被称为“不可变数组”。其数组本身计数与php5一致,但是数组里面的每个键值对的计数,则按前面三条的规则(即如果是字符串也不在计数);如果使用opcache,则代码中的常量数组文字将被转换为不可变数组。

 

再次,这些生活在共享内存,因此不能使用refcounting。

我们的demo例子如下:

<?phpecho '测试字符串引用计数';$a = "new string";$b = $a;xdebug_debug_zval( 'a' );unset( $b);xdebug_debug_zval( 'a' );$b = &$a;xdebug_debug_zval( 'a' );echo '测试数组引用计数';$c = array('a','b');xdebug_debug_zval( 'c' );$d = $c;xdebug_debug_zval( 'c' );$c[2]='c';xdebug_debug_zval( 'c' );echo '测试int型计数';$e = 1;xdebug_debug_zval( 'e' );

看到的输出如下:

三、回收周期

默认的,PHP的垃圾回收机制是打开的,然后有个php.ini设置允许你修改它:zend.enable_gc 。

当垃圾回收机制打开时,算法会判断每当根缓存区存满时,就会执行循环查找。根缓存区有固定的大小,默认10,000,可以通过修改PHP源码文件Zend/zend_gc.c中的常量GC_ROOT_BUFFER_MAX_ENTRIES,然后重新编译PHP,来修改这个值。当垃圾回收机制关闭时,循环查找算法永不执行,然而,根将一直存在根缓冲区中,不管在配置中垃圾回收机制是否激活。

除了修改配置zend.enable_gc ,也能通过分别调用gc_enable() 和 gc_disable()函数在运行php时来打开和关闭垃圾回收机制。调用这些函数,与修改配置项来打开或关闭垃圾回收机制的效果是一样的。即使在可能根缓冲区还没满时,也能强制执行周期回收。你能调用gc_collect_cycles()函数达到这个目的。这个函数将返回使用这个算法回收的周期数。

允许打开和关闭垃圾回收机制并且允许自主的初始化的原因,是由于你的应用程序的某部分可能是高时效性的。在这种情况下,你可能不想使用垃圾回收机制。当然,对你的应用程序的某部分关闭垃圾回收机制,是在冒着可能内存泄漏的风险,因为一些可能根也许存不进有限的根缓冲区。

因此,就在你调用gc_disable()函数释放内存之前,先调用gc_collect_cycles()函数可能比较明智。因为这将清除已存放在根缓冲区中的所有可能根,然后在垃圾回收机制被关闭时,可留下空缓冲区以有更多空间存储可能根。

四、性能影响

1、内存占用空间的节省

首先,实现垃圾回收机制的整个原因是为了一旦先决条件满足,通过清理循环引用的变量来节省内存占用。在PHP执行中,一旦根缓冲区满了或者调用gc_collect_cycles() 函数时,就会执行垃圾回收。

2、执行时间增加

垃圾回收影响性能的第二个领域是它释放已泄漏的内存耗费的时间。

通常,PHP中的垃圾回收机制,仅仅在循环回收算法确实运行时会有时间消耗上的增加。但是在平常的(更小的)脚本中应根本就没有性能影响。

3、在平常脚本中有循环回收机制运行的情况下,内存的节省将允许更多这种脚本同时运行在你的服务器上。因为总共使用的内存没达到上限。

这种好处在长时间运行脚本中尤其明显,诸如长时间的测试套件或者daemon脚本此类。同时,对通常比Web脚本运行时间长的脚本应用程序,新的垃圾回收机制,应该会大大改变一直以来认为内存泄漏问题难以解决的看法。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。