八重樱:面试10家公司,收获9个offer,2020年PHP 面试问题​zhuanlan.zhihu.com

ps:本篇内容包括精选面试题与知识篇。

PHP面试题关于PHP的垃圾回收机制,PHP的垃圾回收机制引用计数 (reference counting) GC 机制,PHP可以自动进行内存管理,清除不需要的对象,PHP面试题分享PHP关于垃圾回收机制的面试题:

★我的php学习交流社群——856460874。群内管理已准备好 整理好的BAT等一线大厂进阶知识体系备好(相关学习资料以及笔面试题)欢迎获取一起晋升=点击加

面试题篇

  • 介绍一下PHP的垃圾回收机制

PHP使用了引用计数(reference counting)GC机制,同时使用根缓冲区机制,当php发现有存在循环引用的zval时,就会把其投入到根缓冲区,当根缓冲区达到配置文件中的指定数量后,就会进行垃圾回收,以此解决循环引用导致的内存泄漏问题。

  • 1. 如果引用计数减少到零,所在变量容器将被清除(free),不属于垃圾;
  • 2. 如果一个zval的引用计数减少后还大于0,那么它会进入垃圾周期。其次,在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾。

每个对象都内含一个引用计数器refcount,每个reference连接到对象,计数器加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、在PHP5.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变量容器,除了包含变量的类型和值,还包括两个字节的额外信息。第一个是"is_ref",是个bool值,用来标识这个变量是否是属于引用集合(reference 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例子如下:

<?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' );

看到的输出如下:

三、回收周期

默认的,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脚本运行时间长的脚本应用程序,新的垃圾回收机制,应该会大大改变一直以来认为内存泄漏问题难以解决的看法。

最后,祝所有大家在面试中过关斩将,拿到心仪offer。

对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家

如果想与一群3-8年资深开发者一起交流学习的话,需要,我的官方群-点击此处。

八重樱:腾讯T3-T4标准精品PHP架构师教程目录大全,只要你看完保证薪资上升一个台阶(持续更新)​zhuanlan.zhihu.com

php 对象转数组_PHP的垃圾回收机制-PHP高级面试题+详解相关推荐

  1. PHP的垃圾回收机制-PHP高级面试题+详解

    面试10家公司,收获9个offer,2020年PHP 面试问题​zhuanlan.zhihu.com ps:本篇内容包括精选面试题与知识篇. PHP面试题关于PHP的垃圾回收机制,PHP的垃圾回收机制 ...

  2. 判断是否存在此对象_JVM的垃圾回收机制,判断对象是否死亡

    这节我们主要讲垃圾收集的一些基本概念,先了解垃圾收集是什么.然后触发条件是什么.最后虚拟机如何判断对象是否死亡. 一.前言 我们都知道Java和C++有一个非常大的区别就是Java有自动的垃圾回收机制 ...

  3. java 堆_JAVA学习笔记 07——堆、栈和垃圾回收机制

    程序执行的内存分析过程: 虚拟机栈(简称:栈)的特点如下: 1. 栈描述的是方法执行的内存模型.每个方法被调用都会创建一个栈帧(存储局部变量.操作数.方法出口等). 2. JVM为每个线程创建一个栈, ...

  4. 垃圾回收机制之复制算法

    我再说一下什么是磁盘碎片化,磁盘碎片化表示删不干净,比如我格式化磁盘,肯定效率高一点,而且删的干净一点,如果一个一个的删除的话,容易产生碎片,有一部分没有被删除掉,你们可以下去自己做一个例子,有的时候 ...

  5. 深入理解 Java 垃圾回收机制

    转载自 http://www.cnblogs.com/andy-zcx/p/5522836.html 深入理解 Java 垃圾回收机制 一:垃圾回收机制的意义 java  语言中一个显著的特点就是引入 ...

  6. java中的年轻态,14、Java垃圾回收机制(示例代码)

    垃圾回收原理和算法 ??Java引入了垃圾回收机制,令C++程序员最头疼的内存管理问题迎刃而解.Java程序员可以将更多的精力放到业务逻辑上面,而不是内存管量上面,大大的提高了开发效率.这是因为Jav ...

  7. 深入理解java垃圾回收机制

    一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理.由于有个垃圾回收机制 ...

  8. java遍历删除原理,Java 垃圾回收机制实现原理

    一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理.由于有个垃圾回收机制 ...

  9. jvm垃圾回收机制_干货|JVM垃圾回收机制

    前言 不同于C++程序员必须自己完成内存的分配.使用和释放,JAVA语言提供了垃圾回收机制(GC,Garbage Collection),所以JAVA程序员仅需要负责分配和使用内存即可,而释放内存则由 ...

最新文章

  1. python减少内存_如何降低 Python 的内存消耗量?
  2. 浏览器从输入url到页面加载完成发生了什么
  3. jzoj4640. 【GDOI2017模拟7.15】妖怪
  4. angularJs关于指令的一些冷门属性
  5. 外键约束 mysql
  6. Configuration Manager 2012 R2系统需求
  7. php调用redis的scan,hscan,zscan 命令
  8. 优雅的编写多线程——原子量
  9. UFS Hibernate介绍--代码部分
  10. 如何制定切实可行的计划并好好执行——2020年,我不想再碌碌无为
  11. 计算机组装拆卸 心得,学习组装电脑的心得体会怎么写?
  12. 本地差分隐私 随机响应_本地化差分隐私:如何面对非可信的世界
  13. AS 使用Statistic插件统计代码行数
  14. 转《七年之前和七年之后》-祭奠高考
  15. excel学习-制作斜线表头
  16. C#毕业设计——基于C#+asp.net+sqlserver的证券术语解释及翻译系统设计与实现(毕业论文+程序源码)——翻译系统
  17. 力天创见仓库客流管控方案
  18. python uniform 函数
  19. UE4蓝图节点文档翻译【目录】--- Retainer
  20. 百度AIstudio绘制饼图,雷达图以及使用中文字体

热门文章

  1. 【高并发】java中的CAS,你需要知道的东西
  2. 20-10-023-安装-KyLin-2.5.2-单机版安装(MAC)成功
  3. 【JVM】ZGC简介
  4. Kudu :主键冲突 status=Already present: key already present
  5. 23-windows下filebeat与logstash与elasticSearch的合并使用
  6. php实现sql server数据导入到mysql数据库_SQL Server数据库导入MySQL数据库的体验_MySQL...
  7. 面试中被问到HashMap的结构,1.7和1.8有哪些区别?这篇做深入分析!
  8. 麦克马斯特大学计算机科学硕士,2020年麦克马斯特大学硕士要上多久才能毕业...
  9. Could not retrieve transaction isolation level from server
  10. docker 安装mongodb集群,多台服务器