zoukankan      html  css  js  c++  java
  • 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恢复,说明是正常变量。

  • 相关阅读:
    如何在centos上安装epel源
    Linux基础命令之cat使用方法大全
    Python正则表达式一: 基本使用方法
    Python 2.7 学习笔记 中文处理
    python 中 json的处理
    centos下网络代理服务器的配置
    centos7 在 vmware下的安装与配置
    Linux学习:find、chmod、ps命令
    Linux学习:netstat命令
    Linux学习:curl 与 wget命令
  • 原文地址:https://www.cnblogs.com/weiluoyan/p/8858624.html
Copyright © 2011-2022 走看看