【PHP7內核剖析】——變量自動GC機制

目錄

引用計數

寫時拷貝

回收時機


前言:這篇文章主要記錄了PHP內存管理中的變量自動GC機制。關於這塊,在我之前的博客 ”淺談PHP7的垃圾回收機制“ 中有粗略的說一些,如果你不想深入的探究的話,看一下那一篇文章即可,這裏我會說的更加深入一些。

我們都知道,PHP中我們每次使用一個變量的時候直接用$符號申明,之後我們就在需要用到的地方直接使用就好了,最後使用完之後,我們將不會再去管它。但是瞭解C或者C++的同學應該知道,一個變量的正常流程應該是現在堆上申請內存,然後在使用完之後一定要將變量的內存釋放。那我們在PHP中爲啥沒有釋放的這一步呢?這是因爲PHP的變量內存是內核自己去釋放的,不僅是PHP,除了C和C++之外,大多數高級語言都是將變量的內存釋放都在內核中實現了。那今天我們就來看一下PHP的內核時怎麼去釋放變量的內存的。

引用計數

引用計數用來記錄當前有多少zval指向同一個zend_value,當新的zval指向這個zend_value,計數器+1,當zval銷燬時,計數器-1。當引用計數爲0時,表明沒有任何變量指向zend_value了,這時候就可以對value進行釋放了。PHP7中將變量的引用計數放到了zend_value結構中,這與之前時不同的,之前的的引用計數信息時存放在zval結構裏面的。我們先看一下PHP中變量類型的內部結構:以string類型爲例:

struct _zend_string {
	zend_refcounted_h gc;
	zend_ulong        h;                /* hash value */
	size_t            len;
	char              val[1];
};

在上面的struct裏面,我們看到有一個成員時gc,這個gc就是用來保存引用計數信息的。再看成員gc,它的類型時zend_refcounted_h,那我們也來看一下這個結構的內部實現:

typedef struct _zend_refcounted_h {
	uint32_t         refcount;			/* reference counter 32-bit */
	union {
		struct {
			ZEND_ENDIAN_LOHI_3(
				zend_uchar    type,
				zend_uchar    flags,    /* used for strings & objects */
				uint16_t      gc_info)  /* keeps GC root number (or 0) and color */
		} v;
		uint32_t type_info;
	} u;
} zend_refcounted_h;

其中,32爲無符號的整形refcount成員就是記錄引用計數的。

舉個例子來說:

$a = array();   //refcount = 1  
$b = $a;        //refcount = 2
$c = $b;        //refcount = 3
unset($b);      //refcount = 2

上面就是引用計數變化的歷程。

注意的是:並不是所有的類型都會用到引用計數,沒有具體value的值是不會用到引用計數的,比如:整型,浮點型,布爾型,NULL,因爲上面4中類型的值是直接存在zval的,所以它們是不會共用value的,拷貝的時候也是深拷貝。還有兩個特殊情況也不會用到引用計數:內部字符串,不可變數組。

寫時拷貝

關於寫時拷貝,它的意思就是指只有在有必要(需要寫的時候)的情況下才進行深拷貝,這樣既可以提高效率,也可以節省空間。上代碼解釋一下:

$a = [1,2];  //a的zend_value的值是[1,2]
$b = $a;     //b的值指向的是a的zend_value
$c = $b;     //c的值也是指向a的zeng_value
$c[] = 3;    //c的值需要變化了,這個時候會copy一個zend_value的內存空間,用來存放修改之後的值

上面就是寫時拷貝的內部原理:只有在寫的時候纔會深度拷貝,否則會指向已有的地址。然而需要我們注意的是:並不是所有類型的value都可以進行復制,比如對象與資源。如果多個變量指向同一個對象,當其中一個變量修改對象時,其修改將反應在所有的變量上。實際上,只有string與array這兩種類型支持value的分離。

回收時機

在自動GC機制中,變量的回收一般有三種情況,函數返回,修改變量,主動銷燬。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章