面试题:介绍一下PHP的垃圾回收机制,哪些陈述是错误的?
PHP面试题PHP垃圾回收机制,PHP垃圾回收机制引用计数(referencecounting)GC机制,PHP可以自动管理内存并删除不必要的对象,PHP面试题分享PHP垃圾回收机制面试题:
面试问题
- 介绍PHP垃圾回收机制
PHP使用引用计数GC机制和根缓冲区机制。如果 PHP 发现有一个 zval 存在循环引用,当 root buffer 达到配置文件中指定的数量时,就会进行垃圾回收,以解决循环引用导致的内存泄漏问题。
- 1。当引用减为零时,可变容器被清空(免费)并且不是垃圾;
- 2。如果zval引用递减后仍然大于0,则进入垃圾循环。其次,在垃圾循环期间,可以通过检查引用计数是否减1以及检查哪些变量容器具有空引用来找出哪些部分是垃圾。
每个对象都包含一个引用计数器。每个引用都连接到该对象,并且计数器加 1。如果引用离开住所或设置为 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代码可能需要很长时间才能运行,但如果有在此期间如果有未引用的变量,会占用内存空间,导致运行缓慢等问题
知识章节
1。概念
垃圾收集是大多数编程语言中包含的内存管理机制。与非托管语言:C、C++ 和 Objective C 需要用户手动管理内存不同,具有 GC 机制的语言:Java、javaScript 和 PHP 可以自动管理内存。
垃圾收集(gc),顾名思义,就是回收废物的意思。这是一种动态存储分配方案。它自动释放程序不再需要的已分配内存块。垃圾回收机制可以让程序员不用过多担心程序内存分配,从而可以将更多的精力投入到业务逻辑上。
垃圾收集机制是当今许多流行的新一代语言的共同特征。例如Python、PHP、C#、Ruby等都使用了垃圾回收机制。
2。 PHP 垃圾回收机制
1.在PHP5.3之前,垃圾收集机制只是简单的“引用读取”。
什么是引用计数? ③ 如果计数器 = 0,则表示内存对象未被使用,内存对象已被销毁,垃圾回收已完成。 并且 PHP 在其生命周期结束后释放该进程/线程所占用的内容。这种方式决定了PHP前期不必考虑太多的内存泄漏。 但是,如果两个或多个对象相互引用形成一个环,则内存对象的计数器不会减至 0;此时,这组内存对象不再有用,而且无法重用,导致内存泄漏。一个现象。 从php5.3开始,使用了新的垃圾回收机制。基于引用计数,实现了复杂的算法来检测内存对象中引用环的存在,以防止内存泄漏。 正如官方文档所说:每个php变量都存在于一个名为“zval”的变量容器中。除了变量的类型和值之外,zval 变量容器还包含两个字节的附加信息。第一个是“is_ref”,它是一个布尔值,用于标识该变量的引用集成员资格。通过这个字节,PHP引擎可以区分普通变量和引用变量。由于 PHP 允许用户使用 & 来使用自定义引用,因此 zval 变量容器还具有内部引用计数机制来优化内存使用。 第二个额外字节是“refcount”,用于指示指向这个zval变量容器的变量(也称为符号)的数量。所有符号都存在于符号表中,并且每个符号都有一个范围。 官方文档说可以使用Xdebug来查看引用计数: 上面例程的输出: 注意。从 PHP7 NTS 开始,不再支持对上述例程的引用。 ,即c=c=c=b=$a后a的引用计数也为1。具体分类如下: 在PHP 7中,z可能是引用计数的,也可能是无引用的。 zval 结构有一个定义它的标志。 ① 对于 null、bool、int 和 double 变量,从不计算引用计数; ②对象和资源类型的重新计数与php5一致; ③ 对于字符串,没有引用的变量被称为“实际字符串”。这些引用的字符串经过重复数据删除(即仅插入一个具有特定内容的字符串),并保证在查询的生命周期内存在,因此无需对它们使用引用计数。如果使用opcache,这些字符串保留在共享内存中,在这种情况下你不能使用引用计数(因为我们的引用计数机制是非原子的); ④对于数组来说,未引用的变量称为不可变数组。数组本身的计数是符合PHP5的,但是数组中每个键值对的计数是基于前面三个规则(即如果是字符串则不计数);如果使用opcache,则代码将常量数组文字转换为不可变数组。 同样,这些位于共享内存中,因此无法使用重新计数。 我们的演示示例是: 您看到的输出是: 3。回收周期 默认情况下,PHP 垃圾回收机制是打开的,并且 php.ini 中有一个设置允许你更改它:zend.enable_gc。 如果启用了垃圾回收机制,当根缓冲区已满时,算法会确定执行循环搜索。根缓冲区有固定大小,默认为10000。可以通过更改PHP源文件Zend/zend_gc.c中的GC_ROOT_BUFFER_MAX_ENTRIES常量然后重新编译PHP来更改该值。如果关闭垃圾收集,则永远不会执行环回算法,但根始终存在于根缓冲区中,无论配置中是否启用垃圾收集。 除了更改 zend.enable_gc 配置之外,您还可以在运行 PHP 时分别调用 gc_enable() 和 gc_disable() 函数来启用和禁用垃圾收集机制。调用这些函数与更改配置元素以打开或关闭垃圾收集机制具有相同的效果。即使根缓冲区未满,也能够强制定期收集。您可以为此调用 gc_collect_cycles() 。该函数返回该算法回收的周期数。 打开和关闭垃圾收集以及启用自动重置的原因是应用程序的某些部分可能对时间敏感。在这种情况下,您可能不想使用垃圾收集。当然,如果您关闭应用程序某些部分的垃圾收集,则会面临内存泄漏的风险,因为某些潜在的根可能不适合有限的根缓冲区。 因此,在调用 gc_disable() 之前先调用 gc_collect_cycles() 释放内存可能是明智的。由于这会删除根缓冲区中存储的所有可能的根,因此如果关闭垃圾收集机制,则可以为空缓冲区留下更多空间来存储可能的根。 4. 性能影响 1. 节省内存占用 首先,实现垃圾收集机制的全部原因是在满足先决条件时通过清理循环引用的变量来节省内存占用。在 PHP 执行期间,当根缓冲区已满或调用 gc_collect_cycles() 函数时,将执行垃圾收集。 2。更长的执行时间 垃圾收集影响性能的另一个方面是释放泄漏内存所需的时间。 通常,PHP 的垃圾回收机制仅在回收算法实际运行时才会增加时间消耗。但在正常(较小)的脚本中,性能根本不应该受到影响。 3。通过在常见脚本中运行回收机制,节省内存允许更多此类脚本在服务器上同时运行。因为内存使用总量还没有达到上限。 对于长时间运行的脚本(例如长时间运行的测试套件或守护程序脚本),此优势尤其明显。与此同时,脚本应用程序的新垃圾收集机制(通常比 Web 脚本运行时间更长)应该会显着改变长期以来内存泄漏难以解决的观点。 作者:八重樱
由于 PHP 是用 C 编写的,所以 C 有一种叫做结构体的东西。这就是我们的 PHP 变量在 C 中的存储方式。
每个 PHP 变量都位于名为 zval 的容器中。除了变量名和值之外,zval容器还包含两个字节的附加信息:
● 其中一个叫做'is_ref',它是一个布尔值,表示这个变量是否存在。属于参考集。通过这个字节我们可以区分普通变量和PHP引用变量。
● 第二个额外字节是'refcount',用于指示指向此容器的变量数量。? 1; <?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'
复制代码
<?php
echo '测试字符串引用计数';
$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' );
复制代码
链接:https://juejin.im/post/6862330373943558157
来源:掘金
版权归作者所有。商业转载请联系作者获取授权。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。