PHPer 高手之路
  • Introduction
  • First Chapter
  • 基础
    • 数据类型和常量
    • 字符串
      • 字符编码
      • 字符编码相关编程
    • 引用变量
    • 运算符与错误控制符@
    • 流程控制与条件判断
      • foreach遍历中的引用
    • 函数
    • 文件及目录处理
  • PHP 数组
    • 基础
    • PHP数组操作
    • 输入流 php://input
    • PHP数组的内部实现
    • PHP数组和数据结构
    • 示例技巧
  • PHP文件编程
    • 文件系统
    • 基础
    • 实例技巧
    • PHP中XML处理
    • PHP中JSON处理
    • PHP中CSV处理
    • 大文件上传
  • 正则表达式
    • 基础
    • 正则的引擎
    • 表达式的优化
    • PHP中正则的使用
  • PHP 编码技巧
    • PHP编码习惯
    • PHP语法糖
    • PHP代码优化
    • PHP重点新特性
    • PHP编码规范
  • PHP选项和运行原理
    • PHP SAPI
    • PHP运行模式及安装方式
    • 附录:进程和线程的Q解
    • Apache下的MPM模式
    • Apache 与 Nginx
    • PHP的运行机制及原理
    • PHP垃圾回收机制
    • PHP配置选项
  • PHP安全
    • 跨站脚本攻击(XSS )
    • 跨站请求伪造(CRSF)
  • PHP 高级特性
    • 异常处理(Exceptions)
    • 代码复用(Trait)
    • 预定义接口(Predefined Interfaces)
    • 魔术方法(Magic Methods)
    • 回调函数、匿名函数&闭包
    • 命名空间(Namespaces)
    • 自动加载(Autoload)
    • 反射(Reflection)
    • 魔术常量(Magic constants)
    • 综合实例
  • 附录:关键词
  • 附录:资料
  • 代码的版本控制
    • SVN
    • Git
      • 疑难杂症
  • Linux
    • Linux原理与基础
    • 常见命令
    • Shell 编程
    • awk 与 sed
    • 命令笔记
  • HTTP 协议
    • 请求方法与返回状态码
    • Cookie、Session 的原理
  • MySQL
    • MySQL表存储引擎
  • 标准PHP库(SPL)
    • 数据结构
      • SplPriorityQueue - 优先队列
      • SplQueue - 队列
      • SplStack - 栈的功能
    • 接口
      • Countable - count统计接口
  • 附录:ElasticSearch
  • PHP数据结构
  • 附录:Rabbitmq
  • 附录:guzzle
  • JavaScript
    • 附录:资料
  • 疑难杂症
Powered by GitBook
On this page

Was this helpful?

  1. PHP选项和运行原理

PHP垃圾回收机制

php中什么是垃圾?

垃圾主要是针对内存的, 如果一个对象, 并没有任何变量引用它,那这个对象就是垃圾.

为什么要清理垃圾?

  • 如果php开启了很多内存空间,但是却没有销毁它.内存会一点点的被吃掉,最终导致内存溢出!

  • 有人说php线程结束的时候会销毁所有的变量,关闭所有打开的句柄资源,不都是自动的吗?为什么我们还需要清理?

  • 如果你写的php代码是个需要长时间执行的呢,例如弄成守护进程?

垃圾回收的机制

PHP如何找到垃圾

第一步, 从所有变量中找到垃圾

所有的变量get_defined_vars函数能够看到所有已经定义的变量,那意味着php本身能存储所有变量或已开辟的内存空间,具体在zend_globals.h中struct _zend_executor_globals 中看到

struct _zend_executor_globals {
    //略
    HashTable *active_symbol_table;//局部变量的符号表
    HashTable symbol_table;//全局变量的符号表
    //略
};

能看到所有的变量,这边变量会被打上视为垃圾的标签

变量本身的定义Zend/zend.h中以看到zval的定义

zend_uint refcount__gc; //这个用来标记有多少个变量指向它
zend_uchar is_ref__gc; //这个用来标记用引用的方式指向它

查看是不是垃圾就看 refcount__gc 是不是为0

$a = array(1);
//$b = $a;
$a[] = $a;
unset($a[1]);
//unset($a);
//$c = &$a;
//$d = &$a;
//$c = null;
//$c =1;
//unset($a);
//unset($a);
xdebug_debug_zval('a');
//var_dump(get_defined_vars());

PHP中的引用是什么?

  • 引用不是C的指针

  • 引用允许用两个变量来指向同一个内容

  • 引用做的第二件事是用引用传递变量

  • 引用做的第三件事是引用返回

第二步.清除垃圾

找到refcount = 0的就清除,并回收内存(5.2以及以前版本)PHP5.3版本中采用了引用计数系统中的同步周期回收(Concurrent Cycle Collection in Reference Counted Systems)算法来清除 , 基本规则是这样的 ,如果引用技术在+1 ,说明变量再用,不是垃圾,如果引用技术本身为0,那就是垃圾,需要被删除, 如果引用计数-1 其为非0 的时候 将其放到某一区块标记为疑似垃圾,然后对其做很多的模拟操作,最后找到真正的垃圾(为了解决自调用$a=array(1);$a[]=&a这样的垃圾)

当我们存储的疑似垃圾的区域满了的时候,就会被执行清除垃圾的操作,前提是开启了垃圾回收机制,当然,默认是打开的php.ini 设置允许你修改它:zend.enable_gc

修改配置zend.enable_gc ,也能通过分别调用gc_enable() 和 gc_disable()函数来打开和关闭垃圾回收机制。调用这些函数,与修改配置项来打开或关闭垃圾回收机制的效果是一样的。你还能调用gc_collect_cycles()函数达到这个目的。它能强制执行周期回收。

PreviousPHP的运行机制及原理NextPHP配置选项

Last updated 5 years ago

Was this helpful?