时间:2014-02-15所属栏目: PHP/PHP框架 来源: 未知 热度:
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中变量及其内存工具的内部暗示(其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,这个算法中文翻译叫做“引用计数”,其头脑很是直观和简捷:为每个内存工具分派一个计数器,当一个内存工具成立时计数器初始化为1(因此此时老是有一个变量引用此工具),往后每有一个新变量引用此内存工具,则计数器加1,而每当镌汰一个引用此内存工具的变量则计数器减1,当垃圾接纳机制运作的时辰,将全部计数器为0的内存工具烧毁并接纳其占用的内存。而PHP中内存工具就是zval,而计数器就是refcount__gc。