垃圾回收:

简称GC。顾名思义,就是废物重利用的意思。
说垃圾回收机制之前,先接触一下内存泄漏。

内存泄漏:

某大神重口味充满画面感的形象解释:

大概意思就是申请了一块地儿拉了会儿屎,拉完后不收拾,那么那块儿地就算是糟蹋了,地越用越少,最后一地全是屎。说到底一句,用了记得还。一定程度上说,垃圾回收机制就是用来擦屁股的。

c语言垃圾回收机制:

如果用过C语言,那么申请内存的方式是malloc或者是calloc,然后你用完这个内存后,一定不要忘了用free函数去释放掉,这就是手动垃圾回收,一般都是大神用这种方式。

php的自动垃圾回收机制是怎样的呢?

这个问题我们先这么想,我们都知道php是C语言实现的。你想想如何用C语言实现对一个变量的统计以及释放。C语言是如何实现一个变量,从声明开始到最后没人用了,就把这个变量所占的内存给释放掉(被垃圾回收)。

PHP进行内存管理的核心算法一共两项:
一是引用计数,二是写时拷贝

声明一个PHP变量的时候,C语言就在底层生成一个叫做zval的struct(结构体),如下:

zval {string "a" //变量的名字是avalue zend_value //变量的值,联合体type string //变量是字符串类型}

zval struct结构体

(1)保存php $a的变量名
(2)php $a的变量类型
(3)php变量$a的zend_value联合体

如果给变量赋值了,比如“hello world”,那么C语言就在底层再生成一个叫做zend_value的union(联合体)

zend_value {string "hello world" //值的内容refcount 1 //引用计数}

zend_value的union(联合体)

(1)保存php $a的变量的值hello world
(2)记录php $a变量引用次数

看到 zval struct结构体和zend_value,如果面试官问你php变量为什么能够保存字符串"123"也能保存数字123,你知道该怎么回答了吧?就答出重点zval中有该变量的类型,当是字符串123的时候,type就是string,此时value指向“123”;当是整数123的时候,zval的type为int,value为123。

何为引用计数?

代码实战解析php变量引用计数

​​​​​​​

$a = 'hello,world';echo xdebug_debug_zval( 'a');//refcount=1$b = $a;echo xdebug_debug_zval( 'a'); //$b引用$a,故变量a,refcount=2$c = $a;echo xdebug_debug_zval( 'a'); //$c引用$a,故变量a,refcount=3unset( $c );echo xdebug_debug_zval( 'a');//删除了$c的引用,故变量a,refcount=2

运行结果:

a:
(refcount=1, is_ref=0)string 'hello,world' (length=11)
a:
(refcount=2, is_ref=0)string 'hello,world' (length=11)
a:
(refcount=3, is_ref=0)string 'hello,world' (length=11)
a:
(refcount=2, is_ref=0)string 'hello,world' (length=11)

何为拷贝复制?

$a = 'hello';$b = $a;//$a赋值给$b的时候,$a的值并没有真的复制了一份echo xdebug_debug_zval( 'a');//$a的引用计数为2$a = 'world';//当我们修改$a的值为123的时候,这个时候就不得已进行复制,避免$b的值和$a的一样echo xdebug_debug_zval( 'a');///$a的引用计数为1

运行结果:

a:
(refcount=2, is_ref=0)string 'hello' (length=5)
a:
(refcount=1, is_ref=0)string 'world' (length=5)

其实,当你把$a赋值给$b的时候,$a的值并没有真的复制了一份,这样是对内存的极度不尊重,也是对时间复杂度的极度不尊重,计算机仅仅是将$b指向了$a的值而已,这就叫多快好省。那么,什么时候真正的发生复制呢?就是当我们修改$a的值为123的时候,这个时候就不得已进行复制,避免$b的值和$a的一样。

通过简单的案例解释清楚了两个要点:引用计数和写时拷贝。

垃圾回收机制:

当一个zval在被unset的时候、或者从一个函数中运行完毕出来(就是局部变量)的时候等等很多地方,都会产生zval与zend_value发生断开的行为,这个时候zend引擎需要检测的就是zend_value的refcount是否为0,如果为0,则直接KO free空出内容来。如果zend_value的recount不为0,这个value不能被释放,但是也不代表这个zend_value是清白的,因为此zend_value依然可能是个垃圾。

(1)当php变量$a的refcount=0时,变量$a就会被垃圾回收
(2)当php变量$a的refcount>0时,变量$a但也可能被认为是垃圾

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

$arr = [ 1 ];$arr[] = &$arr;unset( $arr );

这种情况下,zend_value不会能释放,但也不能放过它,不然一定会产生内存泄漏,所以这会儿zend_value会被扔到一个叫做垃圾回收堆中,然后zend引擎会依次对垃圾回收堆中的这些zend_value进行二次检测,检测是不是由于上述两种情况造成的refcount为1但是自身却确实没有人再用了,如果一旦确定是上述两种情况造成的,那么就会将zend_value彻底抹掉释放内存。

垃圾回收发生在什么时候?

有些同学可能有疑问,就是php不是运行一次就销毁了吗,我要gc有何用?并不是的,首先当一次fpm运行完毕后,最后一定还有gc的,这个销毁就是gc;其次是,内存都是即用即释放的,而不是攒着非得到最后,你想想一个典型的场景,你的控制器里的某个方法里用了一个函数,函数需要一个巨大的数组参数,然后函数还需要修改这个巨大的数组参数,你们应该是函数的运行范围里面修改这个数组,所以此时会发生写时拷贝了,当函数运行完毕后,就得赶紧释放掉这块儿内存以供给其他进程使用,而不是非得等到本地fpm request彻底完成后才销毁。

(1)fpm运行完毕后,最后一定会gc的
(2)运行过程中,也会gc的,内存都是即用即释放的,而不是攒着非得到最后gc

GC处理完整流程图

PHP7垃圾回收机制详解(附GC处理完整流程图)相关推荐

  1. python内存的回收机制_python的内存管理和垃圾回收机制详解

    简单来说python的内存管理机制有三种 1)引用计数 2)垃圾回收 3)内存池 接下来我们来详细讲解这三种管理机制 1,引用计数: 引用计数是一种非常高效的内存管理手段,当一个pyhton对象被引用 ...

  2. go语言垃圾回收机制详解

    Golang GC 垃圾回收机制详解 独一无二的小个性 https://blog.csdn.net/u010649766/article/details/80582153 摘要 在实际使用 go 语言 ...

  3. Python垃圾回收机制详解

    一.垃圾回收机制 Python中的垃圾回收是以引用计数为主,分代收集为辅.引用计数的缺陷是循环引用的问题. 在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存. #e ...

  4. python垃圾回收价格表_Python垃圾回收机制详解

    一.垃圾回收机制 Python中的垃圾回收是以引用计数为主,分代收集为辅.引用计数的缺陷是循环引用的问题. 在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存. #e ...

  5. gc机制 php7_PHP7垃圾回收机制详解(附GC处理完整流程图)

    垃圾回收: 简称GC.顾名思义,就是废物重利用的意思. 说垃圾回收机制之前,先接触一下内存泄漏. 内存泄漏: 某大神重口味充满画面感的形象解释: 大概意思就是申请了一块地儿拉了会儿屎,拉完后不收拾,那 ...

  6. JVM架构和GC垃圾回收机制详解

    JVM架构图分析 下图:参考网络+书籍,如有侵权请见谅 (想了解Hadoop内存溢出请看: Hadoop内存溢出(OOM)分类.参数调优化) JVM被分为三个主要的子系统 (1)类加载器子系统(2)运 ...

  7. java golang gc_Golang GC 垃圾回收机制详解

    摘要 在实际使用 go 语言的过程中,碰到了一些看似奇怪的内存占用现象,于是决定对go语言的垃圾回收模型进行一些研究.本文对研究的结果进行一下总结. 什么是垃圾回收? 曾几何时,内存管理是程序员开发应 ...

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

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

  9. Golang垃圾回收机制详解

    Golang 从第一个版本以来,GC 一直是大家诟病最多的.但是每一个版本的发布基本都伴随着 GC 的改进.下面列出一些比较重要的改动. v1.1 STW v1.3 Mark STW, Sweep 并 ...

最新文章

  1. Json字符串转二维数组
  2. IDEA 构建为了打 jar 包的工程,包含 maven 打 jar 包的过程
  3. 使用webpack、vue来开发一个todo项目
  4. QT中树控件QTreeView开发实例
  5. Javascript 实现TreeView
  6. Zuul之Filter详解
  7. hive与spark的匹配版本汇总
  8. Docker-compose实战——Django+PostgreSQL
  9. mysql 坚向变横向_(排班表一)使用SQL语句使数据从坚向排列转化成横向排列
  10. zz -- QQ圈子感想
  11. 机器学习笔记七之机器学习诊断
  12. android fragment 教程,Android Fragment教程总结
  13. 三星手机怎么把html,三星手机怎么连接电脑 只要四步轻松搞定【图文】
  14. Live Performer for Mac(音频演奏录制软件)v1.0.1
  15. 如何系统学习SWAT模型—建模方法、实例应用、高级进阶
  16. ICCV2021会议论文列表(可下载)
  17. XJOI一级二段题解(g++,即C++),也可视作C++算法竞赛教程
  18. 【jetson-nano】 2.1、安装升级卸载pip3
  19. 名义利率、实际利率、名义贴现率
  20. ODN中主干光交和配线光交的数量比例

热门文章

  1. 小米手环nfc门卡摸拟成功后不能开门_一键开门,7种解锁方式,绿米推出全自动智能锁...
  2. netcore docker_深入浅出 ASP.NET Core 与 Docker 入门课程目标说明
  3. nginx 调用dll_使用DLL中的资源
  4. html时间框自动更新,原生javascript实现自动更新的时间日期
  5. 网关服务Spring Cloud Gateway(三)
  6. 关于API和SDK的理解
  7. DiscuzX系列命令执行分析公开(三连弹)
  8. 隐藏方法不能实现多态性
  9. java的反射和它的类加载机制
  10. 自己写的.Net(C#)代码×××