浅谈PHP5中垃圾回收算法(Garbage Collection)的演化

  次阅读 来源:互联网(转载协议) 2016-03-02 15:50 我要评论(0)

前言:PHP是一门托管型语言,在PHP编程中程序员不需要手工处理内存资源的分配与释放(使用C编写PHP或Zend扩展除外),这就意味着PHP本身实现了垃圾回收机制(Garbage Collection)。现在如果去PHP官方网站(php.net)可以看到,目前PHP5的两个分支版本PHP5.2和PHP5.3是分别更新的,这是因为许多项目仍然使用5.2版本的PHP,而5.3版本对5.2并不是完全兼容。PHP5.3在PHP5.2的基础上做了诸多改进,其中垃圾回收算法就属于一个比较大的改变。本文将分别讨论PHP5.2和PHP5.3的垃圾回收机制,并讨论这种演化和改进对于程序员编写PHP的影响以及要注意的问题。

PHP变量及关联内存对象的内部表示

垃圾回收说到底是对变量及其所关联内存对象的操作,所以在讨论PHP的垃圾回收机制之前,先简要介绍PHP中变量及其内存对象的内部表示(其C源代码中的表示)。

PHP官方文档中将PHP中的变量划分为两类:标量类型和复杂类型。标量类型包括布尔型、整型、浮点型和字符串;复杂类型包括数组、对象和资源;还有一个NULL比较特殊,它不划分为任何类型,而是单独成为一类。

所有这些类型,在PHP内部统一用一个叫做zval的结构表示,在PHP源代码中这个结构名称为“_zval_struct”。zval的具体定义在PHP源代码的“Zend/zend.h”文件中,下面是相关代码的摘录。

typedef union _zvalue_value {

long lval;/* long value */

double dval;/* double value */

struct {

char *val;

int len;

} str;

HashTable *ht;/* hash table value */

zend_object_value obj;

} zvalue_value;

struct _zval_struct {

/* Variable information */

zvalue_value value;/* value */

zend_uint refcount__gc;

zend_uchar type; /* active type */

zend_uchar is_ref__gc;

};

其中联合体“_zvalue_value”用于表示PHP中所有变量的值,这里之所以使用union,是因为一个zval在一个时刻只能表示一种类型的变量。可以看到_zvalue_value中只有5个字段,但是PHP中算上NULL有8种数据类型,那么PHP内部是如何用5个字段表示8种类型呢?这算是PHP设计比较巧妙的一个地方,它通过复用字段达到了减少字段的目的。例如,在PHP内部布尔型、整型及资源(只要存储资源的标识符即可)都是通过lval字段存储的;dval用于存储浮点型;str存储字符串;ht存储数组(注意PHP中的数组其实是哈希表);而obj存储对象类型;如果所有字段全部置为0或NULL则表示PHP中的NULL,这样就达到了用5个字段存储8种类型的值。

而当前zval中的value(value的类型即是_zvalue_value)到底表示那种类型,则由“_zval_struct”中的type确定。_zval_struct即是zval在C语言中的具体实现,每个zval表示一个变量的内存对象。除了value和type,可以看到_zval_struct中还有两个字段refcount__gc和is_ref__gc,从其后缀就可以断定这两个家伙与垃圾回收有关。没错,PHP的垃圾回收全靠这俩字段了。其中refcount__gc表示当前有几个变量引用此zval,而is_ref__gc表示当前zval是否被按引用引用,这话听起来很拗口,这和PHP中zval的“Write-On-Copy”机制有关,由于这个话题不是本文重点,因此这里不再详述,读者只需记住refcount__gc这个字段的作用即可。

PHP5.2中的垃圾回收算法——Reference Counting

PHP5.2中使用的内存回收算法是大名鼎鼎的Reference Counting,这个算法中文翻译叫做“引用计数”,其思想非常直观和简洁:为每个内存对象分配一个计数器,当一个内存对象建立时计数器初始化为1(因此此时总是有一个变量引用此对象),以后每有一个新变量引用此内存对象,则计数器加1,而每当减少一个引用此内存对象的变量则计数器减1,当垃圾回收机制运作的时候,将所有计数器为0的内存对象销毁并回收其占用的内存。而PHP中内存对象就是zval,而计数器就是refcount__gc。

例如下面一段PHP代码演示了PHP5.2计数器的工作原理(计数器值通过xdebug.org得到):

<?php

$val1 = 100; //zval(val1).refcount_gc = 1;

$val2 = $val1; //zval(val1).refcount_gc = 2,zval(val2).refcount_gc = 2(因为是Write on copy,当前val2与val1共同引用一个zval)

$val2 = 200; //zval(val1).refcount_gc = 1,zval(val2).refcount_gc = 1(此处val2新建了一个zval)

本站文章信息来源于网络以及网友投稿,本站只负责对文章进行整理、排版、编辑,是出于传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性。如果您有什么意见或建议,请联系QQ28-1688-302!

人工智能实验室
相关文章相关文章
  • 汤晓鸥:人工智能的中国式文艺复兴

    汤晓鸥:人工智能的中国式文艺复兴

  • 全球陷入"区块链狂热"潮,大规模应用还需等待

    全球陷入"区块链狂热"潮,大规模应用还需等待

  • 区块链最近太火,但A股多家公司明确表态不考虑涉足

    区块链最近太火,但A股多家公司明确表态不考虑涉足

  • 马云的新零售?张近东的智慧零售?抑或是刘强东的第四次零售革命?

    马云的新零售?张近东的智慧零售?抑或是刘强东的第四次零售革命?

网友点评网友点评
阅读推荐阅读推荐

算法 任何一个入门的软件开发人员都会听到这句话:算法是软件的灵魂!近年来大火的机器学习即是在算法在人工智能上的集中体现。今日头条通...

据《日本经济新闻》报道,日本东京大学教授稻叶雅幸等人开发出再现日本人骨骼肌肉构造的机器人。机器人各部位的肌肉和骨骼长度与日本人的平...

以奥黛丽-赫本为原型打造的人形机器人索菲娅首次拜访了印度。索菲娅是世界上首位获得公民身份的机器人,她在12月30日出现在了印度理工学院...

在查获现场,代售点电脑旁的一台机器人通过敲击电脑键盘抢票。 广州日报惠州讯 (全媒体记者秦仲阳 通讯员张中铃摄影报道)2018年春运售票已...