php底层原理之垃圾回收机制(版本一)

PHP7中的垃圾回收机制与原理讲解 PHP快速入门与实战在计算机程序中,垃圾回收指的是一种自动管理内存的技术。在程序执行过程中,分配给它的内存会随着对象的创建和销毁不断发生变化,如果没有垃圾回收,这些不再被使用的内存会一直占用系统资源,最终导致系统崩溃。因此,垃圾回收是保证程序稳定运行和保护计算机系统的必要措施。通过及时回收不再使用的内存,程序中可用的内存空间将被优化使用,从而提高程序的执行效率,并避免由于内存泄漏等问题导致的系统崩溃或其他错误。在这篇博客中,我们将介绍PHP7中的垃圾回收原理。 阅读详情

                                    php底层原理之垃圾回收机制

php垃圾回收机制,对于PHPer来说是一个不陌生但是又不是很熟悉的内容。那么php是怎么实现对不需要的内存进行回收的呢?

php变量的内部存储结构

首先还是需要了解下基础知识,便于垃圾回收原理内容的理解。大家都知道php是由C编写而成的,所以php变量的内部存储结构也会和C语言相关,即zval的结构体:

struct _zval_struct {
    union {
        long lval;
        double dval;
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;
        zend_object_value obj;
    } value;                    //变量value值
    zend_uint refcount__gc;   //引用计数内存中使用次数,为0删除该变量
    zend_uchar type;           //变量类型
    zend_uchar is_ref__gc;    //区分是否是引用变量
};

从上面结构体内容可以看出每一个php变量都会由变量类型、value值、引用计数次数和是否是引用变量四部分组成

注:上面zval结构体是php5.3版本之后的结构,php5.3之前因为没有引入新的垃圾回收机制,即GC,所以命名也没有_gc;而php7版本之后由于性能问题所以改写了zval结构,这里不再表述

引用计数原理

了解了php变量的内部存储结构之后,我们再了解下php变量赋值相关的原理和早期垃圾回收机制

变量容器

非array和object变量

每次将常量赋值给一个变量时,都会产生一个变量容器

举例:

$a = 'chenrui的技术成长之路';
xdebug_debug_zval('a')

结果:

a: (refcount=1, is_ref=0)='chenrui的技术成长之路'

array和object变量

会产生元素个数+1的变量容器

举例:

$b = [
'name' => 'chenrui的技术成长之路',
'number' => 3
];
xdebug_debug_zval('b')

结果:

b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='chenrui的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)

赋值原理(写时复制技术)

了解了常量赋值之后,接下来我们从内存角度思考变量之间的赋值

举例:

$a = [
'name' => 'chenrui的技术成长之路',
'number' => 3
]; //创建一个变量容器,变量a指向给变量容器,a的ref_count为1
$b = $a; //变量b也指向变量a指向的变量容器,a和b的ref_count为2
xdebug_debug_zval('a', 'b');
$b['name'] = 'chenrui的技术成长之路1';//变量b的其中一个元素发生改变,此时会复制出一个新的变量容器,变量b重新指向新的变量容器,a和b的ref_count变成1
xdebug_debug_zval('a', 'b'); 

结果:

a: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='chenrui的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
b: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='chenrui的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
a: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='chenrui的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='chenrui的技术成长之路1', 'number' => (refcount=1, is_ref=0)=3)

所以,当变量a赋值给变量b的时候,并没有立刻生成一个新的变量容器,而是将变量b指向了变量a指向的变量容器,即内存"共享";而当变量b其中一个元素发生改变时,才会真正发生变量容器复制,这就是写时复制技术

引用计数清0

当变量容器的ref_count计数清0时,表示该变量容器就会被销毁,实现了内存回收,这也是php5.3版本之前的垃圾回收机制

举例:

$a = "chenrui的技术成长之路";
$b = $a;
xdebug_debug_zval('a');
unset($b);
xdebug_debug_zval('a');

结果:

a: (refcount=2, is_ref=0)='chenrui的技术成长之路'
a: (refcount=1, is_ref=0)='chenrui的技术成长之路'

循环引用引发的内存泄露问题

但是php5.3版本之前的垃圾回收机制存在一个漏洞,即当数组或对象内部子元素引用其父元素,而此时如果发生了删除其父元素的情况,此变量容器并不会被删除,因为其子元素还在指向该变量容器,但是由于所有作用域内都没有指向该变量容器的符号,所以无法被清除,因此会发生内存泄漏,直到该脚本执行结束

举例:

$a = array( 'one' );
$a[] = &$a;
xdebug_debug_zval( 'a' );

由于该示例不好输出结果,用图表示,如图:
循环引用

举例:

unset($a);
xdebug_debug_zval('a');

如图:
循环引用的内存泄漏

新的垃圾回收机制

php5.3版本之后引入根缓冲机制,即php启动时默认设置指定zval数量的根缓冲区(默认是10000),当php发现有存在循环引用的zval时,就会把其投入到根缓冲区,当根缓冲区达到配置文件中的指定数量(默认是10000)后,就会进行垃圾回收,以此解决循环引用导致的内存泄漏问题

确认为垃圾的准则

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

总结

垃圾回收机制:
1、以php的引用计数机制为基础(php5.3以前只有该机制)
2、同时使用根缓冲区机制,当php发现有存在循环引用的zval时,就会把其投入到根缓冲区,当根缓冲区达到配置文件中的指定数量后,就会进行垃圾回收,以此解决循环引用导致的内存泄漏问题(php5.3开始引入该机制)

 

--------------------------------------------------------------------简易说明-------------------------------------------------------------

                               php垃圾回收和内存管理机制

一、PHP 垃圾回收机制(Garbage Collector 简称GC)

在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾。PHP会将其在内存中销毁;这是PHP的GC垃圾处理机制,防止内存溢出。

当一个PHP线程结束时,当前占用的所有内存空间都会被销毁,当前程序中所有对象同时被销毁。GC进程一般都跟着每起一个SESSION而开始运行的.gc目的是为了在session文件过期以后自动销毁删除这些文件.

二、__destruct /unset

__destruct() 析构函数,是在垃圾对象被回收时执行。 

unset 销毁的是指向对象的变量,而不是这个对象。

三、 Session 与PHP垃圾回收机制

由于PHP的工作机制,它并没有一个daemon线程来定期的扫描Session信息并判断其是否失效,当一个有效的请求发生时,PHP 会根据全局变量 session.gc_probability和session.gc_divisor的值,来决定是否启用一个GC, 在默认情况下,session.gc_probability=1, session.gc_divisor =100也就是说有1%的可能性启动GC(也就是说100个请求中只有一个gc会伴随100个中的某个请求而启动).

PHP垃圾回收机制的工作就是扫描所有的Session信息,用当前时间减去session最后修改的时间,同session.gc_maxlifetime参数进行比较,如果生存时间超过gc_maxlifetime(默认24分钟),就将该session删除。 
但是,如果你Web服务器有多个站点,多个站点时,GC处理session可能会出现意想不到的结果,原因就是:GC在工作时,并不会区分不同站点的session.

那么这个时候怎么解决呢?

1. 修改session.save_path,或使用session_save_path()让每个站点的session保存到一个专用目录, 

2. 提供GC的启动率,自然,PHP垃圾回收机制的启动率提高,系统的性能也会相应减低,不推荐。 
    3. 在代码中判断当前session的生存时间,利用session_destroy()删除.

PHP的内存管理, 分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理. 而第二部分是 zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等.

Zend Memory Manager, 以下简称Zend MM, 是PHP中内存管理的逻辑. 其中有一个关键数据结构: zend_mm_heap

 

Zend MM把内存分为小块内存和大块内存俩种, 区别对待, 对于小块内存, 这部分是最最常用的, 所以追求高性能. 而对于大块内存, 则追求的是稳妥,尽量避免内存浪费.

所以, 对于小块内存, PHP还引入了cache机制,Zend MM 希望通过cache尽量做到, 一次定位就能查找分配.

 

 

PCB之AD层次化原理图设计 PCB之AD层次化(模块化)原理图设计 软件版本:AD17.1.9(bBuild 592) 先上效果图: 可以看到,图中有RS485和W5500这两个部分是复用了原理图,当项目中需要多个功能相同的电路时,这种设计就可以大大节约PCB布局布线的时间,方法后面介绍; 1.首先确定好项目中个部分电路的功能模块 不同功能的电路分开不同原理图画,然后给出输入输出端口,这样方便复用,下面是实例项目的功能划分 2.单个模块电路的接口设计 这里以W5500以太网接口电路为例说明: 主要就分为通讯接口和电源接口: 阅读详情

相关推荐

析构函数 php,PHP中__destruct(),类的析构函数详解

PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用。PHP中__destruct(),类的析构函数通过《PHP中__destruct(),类的构造函数》讲解,现在我们已经知道了什么叫构造方法。那么与构造方法对应的就是析构方法。析构方法允许在销毁一个类之前执行的一些操作或完成一些功能,比如说关闭文件、释放结果集等。析构方法是PHP5...

weixin_39848998的博客 1453

ArcGIS License Server点击启动没反应,许可管理器无法启动怎么办

4 当我们再打开ArcGIS License Server Administrator的时候。3 在【服务】中找到【ArcGIS License Manager】双击。无法启动ArcGIS License Server的情况。在使用ArcGIS的过程中,我们经常会遇到。专注GIS领域知识分享,交流行业软件技巧。欢迎关注,不定期分享GIS各种问题和技巧。1 右击我的电脑——【管理】服务状态——启动,确定即可。启动类型选择——自动。

GIS蒲公英的博客 2万+

php __destruct 有什么用,php 析构方法 __destruct 什么情况下执行

按照官方手册的描述,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。代码演示如下class sf{public function __destruct(){echo __METHOD__ . PHP_EOL;}}$c1 = new sf;$c2 = $c1;echo 'unset $c2' . PHP_EOL;unset($c2);echo 'unset $c1' . PHP_...

weixin_31108679的博客 378

HALCON深度学习模型部署新选择:一份详细的OpenVINO 2021.4 LTS集成与配置避坑指南

本文详细介绍了如何将HALCON深度学习模型与OpenVINO 2021.4 LTS集成,提供环境配置、硬件加速优化及故障排除的实用指南。特别针对Intel独立显卡的AI加速器接口进行优化,帮助机器视觉工程师提升AI推理效率,适用于工业检测等高要求场景。

weixin_42531779的博客 238

开发者的避坑指南:在Apple Silicon Mac上构建RocketMQ Python客户端的完整心路历程

本文详细记录了在Apple Silicon Mac上构建RocketMQ Python客户端的完整过程,重点解决了架构兼容性问题。通过源码编译rocketmq-client-cpp库,修复构建脚本和CMake配置,最终成功在M2芯片MacBook Pro上部署RocketMQ Python客户端,为开发者提供了实用的避坑指南。

Pepper的专栏 696

PHP基础知识点【十一】魔术方法

PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以双下划线前缀。这些魔术方法使用的时候不需要用户自己去调用,而是在特定的情况下会被自动调用。 【1】__construct()与__destruct() PHP中允行开发者在一个类中定义一个方法作为构造方法。具有构造方法的类会在每次创建新对象时先调用此方法,所以非常适...

Tacks的博客 464

科研绘图系列:R语言绘制差异蝴蝶图(Butterfly Chart)

科研绘图系列:R语言蝴蝶图(Butterfly Chart)

专注生信领域 1390

php 析构不执行,PHP析构方法 __destruct() 不触发的两个解决办法

本篇文章主要给大家介绍PHP 析构方法 __destruct() 不触发的两个解决办法。有时候在 PHP 里类循环引用时,会导致 __destruct() 不触发的问题,先上问题代码:...

weixin_42143221的博客 526

TypeError: XGBClassifier.fit() got an unexpected keyword argument ‘early_stopping_rounds‘ 解决方案

本文主要介绍了TypeError: XGBClassifier.fit() got an unexpected keyword argument 'early_stopping_rounds’解决方案,希望能对使用XGBoost的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 1万+

语音识别:PyAudio、SoundDevice、Vosk、openai-whisper、Argos-Translate、FunASR(Python)

本文介绍了Python中常用的音频处理库PyAudio,详细解析了其核心功能、核心概念和典型工作流程。PyAudio是一个跨平台的音频I/O库,支持音频录制、播放、实时流处理和低延迟操作。核心概念包括PyAudio类(管理音频设备和流)和Stream类(代表音频流)。文章重点讲解了open()方法的关键参数、回调函数的使用方式以及典型的工作流程,包括设备查询、流配置和资源释放。PyAudio适用于需要实时音频处理的场景,如语音识别和音频效果处理。

算法工程师 705

PHP的垃圾回收机制(全网详解)

当一个PHP对象不再被引用时,它就成为垃圾。垃圾回收器会定期扫描内存中的所有对象,将没有引用的对象标记为垃圾,并释放它们占用的内存空间,以便其他对象可以使用这些空间。为了避免这种情况的发生,PHP提供了一种手动解除引用的方法,即将对象赋值为null,这样就可以让对象的引用计数器降为0,从而被垃圾回收器释放。然而,在平常脚本中有循环回收机制运行的情况下,内存的节省将允许更多这种脚本同时运行在你的服务器上。在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾。

MrWangisgoodboy的博客 3083

Ubuntu Rtx3090 Cuda11.7 安装 pytorch3d

pytorch ubuntu pytorch3d 安装

G果的博客 2272

MySQL的垃圾回收机制到底是怎样的?使用场景是什么?底层原理是什么?

1. 为什么需要垃圾回收?系统稳定性防止资源泄漏导致性能下降或崩溃。资源优化及时释放未使用的内存或磁盘空间,提高性能。数据一致性清理未提交事务或过期日志,确保数据一致性。2. 底层原理总结临时表清理查询完成后,MySQL 自动释放与临时表相关的内存。事务回滚段清理对于未提交的事务,InnoDB 使用 undo log 记录旧版本数据。当事务完成或回滚时,undo log 被清理。数据页回收InnoDB 使用后台线程(如)清理被删除或更新后遗留的数据页。日志轮转。

长风破浪会有时的博客 1054

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

php底层原理之垃圾回收机制

php垃圾回收机制,对于PHPer来说是一个不陌生但是又不是很熟悉的内容。那么php是怎么实现对不需要的内存进行回收的呢? php变量的内部存储结构 首先还是需要了解下基础知识,便于垃圾回收原理内容的理解。大家都知道php是由C编写而成的,所以php变量的内部存储结构也会和C语言相关,即zval的结构体: struct _zval_struct { union { ...

mysteryflower的专栏 370

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

PHP 的垃圾回收机制的底层实现是怎样的?

【代码】PHP 的垃圾回收机制的底层实现是怎样的?

长风破浪会有时的博客 995

PHP5底层原理之垃圾回收机制

概念时光小说 https://wap.youxs.org/ 垃圾回收机制 是一种内存动态分配的方案,它会自动释放程序不再使用的已分配的内存块。 垃圾回收机制 可以让程序员不必过分关心程序内存分配,从而将更多的精力投入到业务逻辑。 与之相关的一个概念,内存泄露 指的是程序未能释放那些已经不再使用的内存,造成内存的浪费。 那么 PHP 是如何实现垃圾回收机制的呢? PHP变量的内部存储结...

代码小牛的博客 396

php7垃圾回收机制是什么,php底层原理之垃圾回收机制

php垃圾回收机制,对于PHPer来说是一个不陌生但是又不是很熟悉的内容。那么php是怎么实现对不需要的内存进行回收的呢?php变量的内部存储结构首先还是需要了解下基础知识,便于垃圾回收原理内容的理解。大家都知道php是由C编写而成的,所以php变量的内部存储结构也会和C语言相关,即zval的结构体:struct _zval_struct {union {long lval;double dval...

weixin_30303283的博客 327

PHP中Session函数底层原理以及session的垃圾回收机制

一、php session函数的原理 session_id作用 重用现有的回话,如果没有就创建,感觉这个函数作用不是很大,我在php这边打印不好使。 session_start作用 1、没有会话,根据session.name = PHPSESSID生成Cookie,并发送给客户端。 2、打开与介质的连接通道,读取相应的id内容到变量$_SESSION中。 session_unset作用...

藏经阁 932

php底层的运行机制与原理

为了让PHP能够高效地处理各种复杂的业务逻辑,开发者们为其构建了一个由多个关键部件组成的强大体系结构。下面我们就来了解一下其中最重要的几个部分。SAPI层:Server Application Programming Interface (SAPI) 层定义了PHP与其他应用程序之间的接口标准,允许PHP以多种方式与外部世界交互。:作为PHP的心脏,Zend引擎承担着解析PHP代码、管理内存分配以及执行实际计算的任务。扩展库:除了内建的功能之外,PHP还支持通过扩展的形式添加额外的能力。

小发猫 1686

php7 垃圾回收机制

在php中的变量占用的空间,是不需要我们手动回收的。内核帮我们处理了这一部分的工作。相比C,这大大方便了我们的操作。 本篇主要讲解 变量的 GC机制 文章目录 zval 的结构 循环引用造成的内存泄漏 object和array的回收过程 垃圾回收的原理 例子 在了解我们 php GC 时,我觉得我有必要介绍一下们的 php 的变量在底层的实现。 zval 的结构 // php 变量对于的...

lxw1844912514的博客 1586

PHP垃圾回收机制底层原理:从ZVAL到GC算法

PHP的垃圾回收机制采用引用计数与循环引用GC算法的组合模式。底层通过ZVAL结构体存储变量信息,其中引用计数(refcount)是基础回收依据,当计数归零时释放内存。但该机制无法处理循环引用问题,PHP5.3引入复合类型专用GC算法:将疑似循环引用的变量放入候选区,通过模拟减引用计数识别真正垃圾,最后批量回收。GC会在缓冲区满、脚本结束或手动调用时触发。在常驻进程开发中,应避免制造深层循环引用,合理使用手动GC控制内存。理解这套机制有助于编写高效、健壮的PHP代码。

2603_96171993的博客 527

php5和7垃圾回收的区别,PHP5底层原理之垃圾回收机制

概念垃圾回收机制 是一种内存动态分配的方案,它会自动释放程序不再使用的已分配的内存块。垃圾回收机制 可以让程序员不必过分关心程序内存分配,从而将更多的精力投入到业务逻辑。与之相关的一个概念,内存泄露 指的是程序未能释放那些已经不再使用的内存,造成内存的浪费。那么 PHP 是如何实现垃圾回收机制的呢?PHP变量的内部存储结构首先还是需要了解下 基础知识,便于对垃圾回收原理内容的理解。PHP 所有类型...

weixin_29596485的博客 227

php底层原理之变量(一)

上次跟大家讲了垃圾回收机制后,有些小伙伴对底层原理比较感兴趣,私信问我了一些关于变量的相关知识,既然大家对变量比较感兴趣,那么这次我们来系统的讲一下变量的底层原理 变量结构 首先,我们还是先摆上我们的zval结构体,即php所有变量都会以zval结构体的形式实现 struct _zval_struct { union { long lval; double dval; struct ...

weixin_34413802的博客 527

php 结构体_php底层原理之垃圾回收机制

php垃圾回收机制,对于PHPer来说是一个不陌生但是又不是很熟悉的内容。那么php是怎么实现对不需要的内存进行回收的呢?php变量的内部存储结构首先还是需要了解下基础知识,便于垃圾回收原理内容的理解。大家都知道php是由C编写而成的,所以php变量的内部存储结构也会和C语言相关,即zval的结构体:struct _zval_struct {union {long lval;double dval...

weixin_39835965的博客 64

PHP 垃圾回收机制(GC),知识体系一共包含哪些部分?底层原理是什么?

模块内容引用计数基础内存管理写时复制性能优化循环引用GC 的处理对象根缓冲区存储候选对象三色标记算法核心回收算法GC 触发自动 / 手动状态监控手动回收Swoole 调试内存泄漏防控。

长风破浪会有时的博客 819
上一篇: PHP内核的存储机制(分离/改变)
下一篇: ActiveMQ
chenrui310
博客等级 码龄15年 165粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值