1.应用场景

了解学习PHP[内存]垃圾回收机制, 帮助理解编程语言的运行机制, 提高开发水平.

2.操作/学习

1.文档

PHP的垃圾回收机制以及大概实现 - 王召波 - 博客园

PHP垃圾回收机制理解 - 张宇航 - 博客园

PHP: 垃圾回收机制 - Manual -- 【基本上】任何时候,都先把官网上的介绍看完了,再看其他的知识点

2. 整理输出

2.1 介绍

垃圾回收是一个多数编程语言中都带有的内存管理机制。

与非托管性语言相反:C, C++ 和 Objective C,用户需要手动收集内存,

带有 GC 机制的语言:Java, javaScript 和 PHP 可以自动管理内存。

垃圾回收机制(GC)顾名思义,就是废物重利用的意思,是一种动态存储分配的方案。

它会自动释放程序不再需要的已分配的内存块。

垃圾回收机制可以让程序员不必过分关心程序内存分配,从而将更多的精力投入到业务逻辑。

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

2.2 实现方式

1. 在PHP5.3版本之前, 使用的垃圾回收机制是单纯的“引用计数”。

2. 随着PHP的发展,PHP开发者的增加以及其所承载的业务范围的扩大,在PHP5.3中引入了更加完善的垃圾回收机制,新的垃圾回收机制【引用计数 + 根缓存区机制】解决了无法处理循环的引用内存泄漏问题。

PHP进行内存管理的核心算法一共两项:

一是引用计数,二是写时拷贝。

请(please)理(bei)解(song)

第一项. 引用计数

使用的是“引用计数”方式进行回收。

简单地理解的话,

就是每个分配的内存区域都有一个计数器,记录有多少个变量指针指向这片内存。

当指向该片内存的指针数量为0,那么该片内存区域就可以被回收。

引用计数计数简单,强大,但是有一个致命的缺陷,就是环状引用。

<?php

$a = [];
$a[] = &$a; // 第一次留意这样使用
unset($a);

变量$a引用了自己,形成一个环。

$a被unset,但由于存在环状引用,因此$a之前指向的内存的引用计数为1,因此该内存区域不会被垃圾回收机制回收。
 
PHP 5.3 针对这个重大的缺陷做了优化。

虽然其基础仍然是引用计数,但是在做了一些改良,能够将 环状引用导致的内存泄露控制在一定的规模以内。
当然,这并不是说你可以随便滥用内存,编写代码时仍然要小心为上!// This is the key point !!

其他要点:
1. PHP脚本运行完毕,该脚本申请的所有内存空间都会释放,不管是否存在环状引用。

因此环状引用内存泄露的问题一般只影响长时间运行的程序脚本。

补充:

会在大并发量下,执行期间,内存也会飙升,因为内存尚未释放,尤其是大对象/数组的数据类型

2. 垃圾回收机制需要满足一定的条件才会执行。因此unset后,系统并不一定会立即回收垃圾

3. unset的作用。
unset只是断开一个变量到一块内存区域的连接,同时将该内存区域的引用计数-1”。

也就是说,如果有一个以上的变量指向同一个内存区域,或者存在环状引用,那么unset不会使内存区域释放。

断开也说明unset并不会直接删除内存区域,而只是改变其引用计数而已。

4. $xx = null的作用。
$a = null 是直接将$a 指向的数据结构置空,同时将其引用计数归0。

根据我对这个定义的理解,= null操作可以立即释放掉内存空间!

因此很多PHP技巧中不厌其烦地对我们说,先将变量设为null,再unset。【问题:这种情况,引用计数归0,再unset,会怎样?

理解其深层原理后,我才彻底理解了这样做的原因!= null 才是王道!

第二项. 写时拷贝

即:

变量的普通赋值与引用赋值

两者的区别:

PHP变量的赋值和引用以及传值与传引用的区别_william_n的博客-CSDN博客

<?php

// 先不要问为什么非要加mt_rand,不然,绝笔说不过来了,到处都是坑

$a = 'hello' . mt_rand( 1, 1000 );
$b = $a;
$a = 123;
echo $b . PHP_EOL;

运行结果,不用我说吧,脚趾头都知道是'hello'.mt_rand( 1, 1000 )的结果,绝对不可能是123。

其实,当你把$a赋值给$b的时候,$a的值并没有真的复制了一份,这样是对内存的极度不尊重,

也是对时间复杂度的极度不尊重,计算机仅仅是将$b指向了$a的值而已,这就叫多快好省。

那么,什么时候真正的发生复制呢?

就是当我们修改$a的值为123的时候,这个时候就不得已进行复制,避免$b的值和$a的一样。

Q: 什么样的情况会导致zend_value的refcount不为0,但是这个zend_value却是个垃圾呢?

A: PHP7 两种情况:

  1. 数组:数组的某个成员使用&引用自己

  2. 对象:对象的某个成员引用对象自己

    请理(bei)解(song),一般面试,你能回答到这一步,已经非常屌了!

Note:

Redis中AOF日志重写也用到了写时复制技术

有些技术,在很多组件/服务中都有用到,要学会总结,类比。

2.3 回收周期 与 回收函数/方式

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

当垃圾回收机制打开时,算法会判断每当根缓存区存满时,就会执行循环查找。

根缓存区有固定的大小,默认10,000,可以通过修改PHP源码文件Zend/zend_gc.c中的常量GC_ROOT_BUFFER_MAX_ENTRIES,然后重新编译PHP,来修改这个值。

当垃圾回收机制关闭时,循环查找算法永不执行,然而,根将一直存在根缓冲区中,不管在配置中垃圾回收机制是否激活。---- 这句话是什么意思?TBD

除了修改配置zend.enable_gc ,也能通过分别调用gc_enable() 和 gc_disable()函数在运行PHP时来打开和关闭垃圾回收机制。

调用这些函数,与修改配置项来打开或关闭垃圾回收机制的效果是一样的。

即使在可能根缓冲区还没满时,也能强制执行周期回收。

你能调用gc_collect_cycles()函数达到这个目的。

这个函数将返回使用这个算法回收的周期数。--- 执行这个函数是否会有其他问题,比如伴随的副作用?参见4.性能第2点

允许打开和关闭垃圾回收机制并且允许自主的初始化的原因,是由于你的应用程序的某部分可能是高时效性的。在这种情况下,你可能不想使用垃圾回收机制。

当然,对你的应用程序的某部分关闭垃圾回收机制,是在冒着可能内存泄漏的风险,因为一些可能根也许存不进有限的根缓冲区。

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

使用哪些函数可以进行垃圾回收

gc_collect_cycle()

unset // 不会一定会清理变量,会让引用计数减1,从而判断是否为0....

赋值null // 直接将$a 指向的数据结构置空,同时将其引用计数归0 -- 虽然可以被回收,但是不是立马回收,而是等待下一个回收周期 -- 参见下面红色

所以可以结合: 先将变量赋值null,然后执行unset()

4. 性能影响

PHP: 性能方面考虑的因素 - Manual

在上一节我们已经简单的提到:回收可能根有细微的性能上影响,但这是把PHP 5.2与PHP 5.3比较时才有的。尽管在PHP 5.2中,记录可能根相对于完全不记录可能根要慢些,而PHP 5.3中对 PHP run-time 的其他修改减少了这个性能损失。

这里主要有两个领域对性能有影响。第一个是内存占用空间的节省,另一个是垃圾回收机制执行内存清理时的执行时间增加(run-time delay)。我们将研究这两个领域。

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

2、执行时间增加
垃圾回收影响性能的第二个领域是它释放已泄漏的内存,耗费的时间。
通常,PHP中的垃圾回收机制,仅仅在循环回收算法确实运行时会有时间消耗上的增加。

但是在平常的(更小的)脚本中应根本就没有性能影响。

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

这种好处在长时间运行脚本中尤其明显,诸如长时间的测试套件或者daemon脚本此类。

同时,对通常比Web脚本运行时间长的脚本应用程序,新的垃圾回收机制,应该会大大改变一直以来认为内存泄漏问题难以解决的看法。

补充问题:

PHP的GC有Full GC吗?

官方文档和网上资料并没有发现PHP 有Full GC一说。

会跟Java一样,当发生Full GC时,会导致整个进程/线程暂停/停顿?

从官方文档和网上资料来看,没有也不会。

5. 总结思考

PHP 的GC机制与Java的GC机制似有不同,还有其他语言的GC

需要后续研究。

后续补充

...

3.问题/补充

TBD

4.参考

PHP的垃圾回收机制以及大概实现 - 王召波 - 博客园   // PHP的垃圾回收机制以及大概实现  -- 推荐

PHP垃圾回收机制理解 - 张宇航 - 博客园   // PHP垃圾回收机制理解 -- 推荐

后续补充

...

PHP - 垃圾回收机制收集相关推荐

  1. java的垃圾回收机制包括:主流回收算法和收集器(jvm的一个主要优化方向)

    2019独角兽企业重金招聘Python工程师标准>>> java的垃圾回收机制是java语言的一大特色,解放了开发人员对内存的复杂控制,但如果你想要一个高级java开发人员,还是需要 ...

  2. 详细介绍Java垃圾回收机制

    垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机 ...

  3. Python3.5源码分析-垃圾回收机制

    Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的垃圾回收概述 随着软硬件的发展,大多数语言都已 ...

  4. 深入浅出Java垃圾回收机制

    2019独角兽企业重金招聘Python工程师标准>>> 对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何 ...

  5. 安卓 java内存碎片_理解Android Java垃圾回收机制

    Jvm(Java虚拟机)内存模型 从Jvm内存模型中入手对于理解GC会有很大的帮助,不过这里只需要了解一个大概,说多了反而混淆视线. Jvm(Java虚拟机)主要管理两种类型内存:堆和非堆. 堆是运行 ...

  6. java垃圾回收机制_笔记 | Java垃圾回收机制

    本文经授权转载自程序员杂货铺(ID:speakFramework) 垃圾回收 最近上海的小伙伴是不是要被强垃圾分类搞疯了???哈哈哈哈 上海是个走在前列的城市啊,不光骑自行车闯红灯要被罚钱,垃圾不分类 ...

  7. JVM的垃圾回收机制详解和调优

    1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都使用类似的 ...

  8. JAVA垃圾回收机制概要

    垃圾回收是JAVA中的一个大知识点,也是一个著名知识点,毕竟JAVA号称自己先进性的时候总是会带上垃圾回收.于是,它也成了面试中的常客,面试官动不动的就要你解释下什么是垃圾回收,以及它的原理是什么.当 ...

  9. 成为JavaGC专家(1)—深入浅出Java垃圾回收机制

    2019独角兽企业重金招聘Python工程师标准>>> 对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何 ...

  10. python 内存回收机制_Python垃圾回收机制是什么

    不同于C/C++,像Python这样的语言是不需要程序员写代码来管理内存的,它的GC(Garbage Collection)机制 实现了自动内存管理.GC做的事情就是解放程序员的双手,找出内存中不用的 ...

最新文章

  1. 收到邮件乱码html,为什么我发的html格式邮件收到的是乱码呢?(100分)
  2. 一个比较简单、非常简单的计算器
  3. Semantic UI实现一个landing page
  4. JSTL分割字符 fn:split()
  5. java中的Attribute类_java培训技术ModelAttribute注解修饰POJO类型的入参
  6. unity快捷放置物体操作
  7. java工程师占比_2020年Java工程师就业分析
  8. Ubuntu20.04如何卸载软件
  9. 计算机组成原理自考pdf,全国高等教育自学考试计算机组成原理.pdf
  10. 0xbc指令 st75256_HGO2401603初始化代码ST75256驱动程序
  11. 睡眠分期matlab代码,非接触式睡眠分期方法与流程
  12. git 拉取子目录 child-dir (父目录为:parent-dir)
  13. 网狐精华版后台修改记录
  14. 机器学习:数学加强(二)——条件概率、贝叶斯公式、常见分布、协方差、相关系数、切比雪夫不等式、大数定律
  15. 转:著名的100个管理定律点评1 -- 管人用人育人留人之道
  16. MySQL之23:59:59进位
  17. 我的程序员转行过程,聊聊程序员的职业出路在哪里?
  18. 使用 Laragon 在 Windows 中搭建 PHP开发环境及常见问题解决
  19. C++学习——布尔型,操作符别名,函数和引用
  20. canvas图片绘制-两张图片的叠加

热门文章

  1. 五、SPR 单一职责
  2. linux启动速度优化
  3. 64位处理器_32位和64位Windows系统差别在哪里
  4. 用计算机怎么弹两只老虎,七键两只老虎曲谱_64键的电子琴怎么弹两只老虎1234567按哪个键...
  5. HighNewTech:元宇宙(metaverse)的简介(多角度理解与探讨)、发展历史、现状与未来
  6. [Excel函数] INDEX函数 | MATCH函数
  7. 【pandas】reset_index函数详解
  8. magisk安装失败_俄罗斯官改MIUI MiRoom安装刷入教程
  9. 当天剩余时间,当月剩余时间(秒数),用于redis设置过期时间
  10. 用Nmap工具查找Downadup/Conficker的蠕虫病毒源