• PHP 内存管理 写时复制 垃圾回收


    PHP中的变量是不需要手动释放的,内核帮我们实现了变量的内存管理,包括内存的分配和回收

    变量深拷贝带来的问题就是效率和内存浪费严重。

    解决深拷贝:1、引用计数 2、写时复制

    PHP变量的内存管理就是基于这两点实现的

    当变量赋值、引用的时候不是进行深拷贝,而是多个变量共用一个value,引用计数来记录这个变量被引用过多少次,当其中的一个变量发生变化时将无法与其他的变量共用

    value时,这个时候就需要进行深拷贝进行分离value,这就是写时复制。

    引用计数:

           用来记录当前有多少个zval指向同一个zend_value,当有新的zval指向这个value时,计数器+1,当zval销毁时,计数书-1,当计数器为0,value就释放来。

    PHP7的引用计数保存在了zend_value中,成员gc用来保存引用计数的。PHP中的局部变量zavl分配在zend_execute_data结构上,也就是我们调试的execute_ex函数中的

    execute_data变量,它是运行期间最重要,最关键的一个结构,用于局部变量的分配、保存执行位置、调用上下文切换等。

    写时复制:

           它只有在有必要的时候即发生写的时候才进行深拷贝,可以很好的提高效率,例如Linux操作系统中fork子进程时并不会立即复制父进程的地址空间,而是让父子进程共享一个内存空间,只有在需要写入的时候才会复制地址空间,从而使各个进程拥有各自独立的地址空间,也就是说资源的复制是在需要写入的时候才会进行,在此之前,以只读方式共享。也并不是所有的类型都可以进行复制,对象资源就无法进行复制。

    自动GC回收:

          在zval断开value的执行是如果发现refounct=0则会直接释放value,这就是变量的回收时机,发生断开的两种常用情况为修改变量与函数返回时,修改变量是会断开value的指向,函数返回时会释放所有的变量。使用unset()函数也可以主动销毁一个变量

    垃圾回收:

         通过引用计数实现了变量的自动GC机制,但是有一种情况是这个机制无法解决的,从而因变量无法回收导致内存始终得不到释放,造成内存泄漏。这种情况就是循环引用,循环引用就是引用了自身导致无法释放,比如数组中元素引用了这个数组。因为这种因为循环引用而导致无法释放的变量称之为垃圾,PHP引用了另一种机制来对这些垃圾进行回收,也就是垃圾回收器:

            这里要明确,如果一个变量value的refcount减少到0,value释放,不属于垃圾。如果一个变量的refcount减少之后大于0,那这可能是垃圾,垃圾回收器会把这种变量收集起来,垃圾回收器会把这种垃圾保存到一个buffer缓存区,等达到一定数量后就会启动垃圾鉴定回收程序,回收算法原理其实很简单,既然垃圾回收是因为引用自身引起的啊,那我就把value的refcount减1,如果返回是0就说明是垃圾,否则再把减1恢复,说明是正常变量。

  • 相关阅读:
    Easy-Mock模拟get接口和post接口实例
    本地部署Easy Mock
    用matplotlib和pandas绘制股票MACD指标图,并验证化交易策略
    向大家介绍我的新书:《基于股票大数据分析的Python入门实战》
    在windows环境里,用Docker搭建Redis开发环境(新书第一个章节)
    谈谈最近副业挣钱的感受,一要形成体系,二要找平台加持
    进大厂也就这回事,工作后2到3年进大厂操作指南
    最近录制视频挣钱的经过和体会
    以外派的身份进大厂,或许条程序员升级的途径
    面试中更多会考核相关技能的项目经验——再论程序员该如何准备面试
  • 原文地址:https://www.cnblogs.com/weiluoyan/p/8858624.html
Copyright © 2020-2023  润新知