溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

php中g(shù)c指的是什么

發(fā)布時(shí)間:2022-03-10 15:43:28 來(lái)源:億速云 閱讀:172 作者:iii 欄目:編程語(yǔ)言

本篇內(nèi)容主要講解“php中g(shù)c指的是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“php中g(shù)c指的是什么”吧!

在php中,gc全稱(chēng)“Garbage Collection”,中文意思為“垃圾回收”,是一種動(dòng)態(tài)內(nèi)存管理機(jī)制,它會(huì)自動(dòng)釋放程序不再需要的已分配的內(nèi)存塊。GC機(jī)制可以讓程序員不必過(guò)分關(guān)心程序內(nèi)存分配,從而將更多的精力投入到業(yè)務(wù)邏輯。

php中g(shù)c指的是什么

本教程操作環(huán)境:windows7系統(tǒng)、PHP7.1版、DELL G3電腦

在php中,gc全稱(chēng)“Garbage Collection”,中文意思為“垃圾回收”,是一種動(dòng)態(tài)內(nèi)存管理機(jī)制。

垃圾回收機(jī)制(GC)會(huì)自動(dòng)釋放程序不再需要的已分配的內(nèi)存塊。自動(dòng)回收內(nèi)存的過(guò)程叫垃圾收集。

垃圾回收機(jī)制(GC)可以讓程序員不必過(guò)分關(guān)心程序內(nèi)存分配,從而將更多的精力投入到業(yè)務(wù)邏輯。

在現(xiàn)在的流行各種語(yǔ)言當(dāng)中,垃圾回收機(jī)制是新一代語(yǔ)言所共有的特征。

垃圾的產(chǎn)生

PHP7 中復(fù)雜類(lèi)型,像字符串、數(shù)組、對(duì)象等的數(shù)據(jù)結(jié)構(gòu)中,頭部都有一個(gè) gc, 這個(gè) gc 的作用就是用來(lái)對(duì)垃圾回收的支持。當(dāng)變量賦值、傳遞時(shí),會(huì)增加 value 的引用數(shù), unset、return 等釋放變量時(shí)再減掉引用數(shù),減掉后如果發(fā)現(xiàn) refcount 變?yōu)?0 則直接釋放 value,這是變量的基本回收過(guò)程。

不過(guò)有一種問(wèn)題是這個(gè)機(jī)制無(wú)法解決的,就是循環(huán)引用的問(wèn)題。

什么是循環(huán)引用呢? 簡(jiǎn)單說(shuō)就是變量的內(nèi)部里存的 value 又引用了變量自身。 這種比較經(jīng)常發(fā)生在數(shù)組和對(duì)象類(lèi)型的變量上。

這里先講一下引用,即 zend_reference 這個(gè)類(lèi)型,這個(gè)是 PHP7 新增的變量類(lèi)型,當(dāng)對(duì)變量使用 “&” 操作時(shí),會(huì)創(chuàng)建新的中間結(jié)構(gòu)體 zend_reference,這個(gè)結(jié)構(gòu)體會(huì)真正的指向?qū)?yīng)的 value 結(jié)構(gòu)。

舉個(gè)例子:

// 當(dāng)進(jìn)行如下賦值操作時(shí)
$a = 'hello'; // $a -> zend_string
$b = $a; // $b,$a -> zend_string
$c = &$b; // $c,$b -> zval(type = IS_REFERENCE, refcount = 2) -> zend_string

最終會(huì)變成如下這樣:

php中g(shù)c指的是什么

即 $b 和 $c 的 zval 是通過(guò)中間結(jié)構(gòu)體 zend_reference 再指向最終的 zend_string。

回到循環(huán)引用的問(wèn)題,舉個(gè)數(shù)組循環(huán)引用例子:

$a = [1];
$a[] = &$a;
unset($a);

使用 & 操作之后,變量 a 就變成了引用類(lèi)型且引用計(jì)數(shù) refcount 為 2,而又賦值給自己里面的元素,即變量 a 變成了自己引用自己。

具體如下如所示:

php中g(shù)c指的是什么

當(dāng) unset 之后就變成下圖這樣:

php中g(shù)c指的是什么

即 $a 所在的 zval 類(lèi)型已經(jīng)變成了 IS_UNDEF 了,zend_reference 結(jié)構(gòu)體的引用計(jì)數(shù)減 1,但是仍然大于 0,這時(shí)候,這部分結(jié)構(gòu)體就變成了垃圾,對(duì)此不處理的話,就可能會(huì)造成內(nèi)存泄露。這里就需要垃圾收集器將這部分收集到緩沖區(qū),之后進(jìn)行回收處理。

回收過(guò)程

如果當(dāng)變量的 refcount 減小后大于 0,PHP 并不會(huì)立即對(duì)這個(gè)變量進(jìn)行垃圾鑒定和回收,而是放入一個(gè)緩沖區(qū)中,等這個(gè)緩沖區(qū)滿了以后 (10000 個(gè)值) 再統(tǒng)一進(jìn)行處理,加入緩沖區(qū)的是變量 zend_value 里的 gc,目前垃圾只會(huì)出現(xiàn)在數(shù)組和對(duì)象兩種類(lèi)型中,數(shù)組的情況上面已經(jīng)介紹了,對(duì)象的情況則是成員屬性引用對(duì)象本身導(dǎo)致的,其它類(lèi)型不會(huì)出現(xiàn)這種變量中的成員引用變量自身的情況,所以垃圾回收只會(huì)處理這兩種類(lèi)型的變量。

gc 的結(jié)構(gòu) zend_refcounted_h 具體如下:

typedef struct _zend_refcounted_h {
    uint32_t         refcount; // 記錄 zend_value 的引用數(shù)
    union {
        struct {
            zend_uchar    type,  // zend_value的類(lèi)型, 與zval.u1.type一致
            zend_uchar    flags, 
            uint16_t      gc_info // GC信息,記錄在 gc 池中的位置和顏色,垃圾回收的過(guò)程會(huì)用到
        } v;
        uint32_t type_info;
    } u;
} zend_refcounted_h;

一個(gè)變量只能加入一次緩沖區(qū),為了防止重復(fù)加入,變量加入后會(huì)把 zend_refcounted_h.gc_info 置為 GC_PURPLE,即標(biāo)為紫色,后續(xù)不會(huì)重復(fù)插入。

垃圾緩沖區(qū)是一個(gè)雙向鏈表,等到緩存區(qū)滿了以后則啟動(dòng)垃圾檢查過(guò)程:遍歷緩沖區(qū),對(duì)當(dāng)前變量的所有成員進(jìn)行遍歷,然后把成員的 refcount 減 1 (如果成員還包含子成員則也進(jìn)行遞歸遍歷,即深度優(yōu)先遍歷),最后再檢查當(dāng)前變量的引用,如果減為了 0 則為垃圾。這個(gè)算法的原理核心是:垃圾是由于成員引用自身導(dǎo)致的,那么就對(duì)所有的成員減一遍引用,如果發(fā)現(xiàn)最后變量本身的 refcount 變?yōu)榱?0 則就表明其引用全部來(lái)自自身成員,即其他任何地方都不再使用它,那么它就是垃圾,需要被回收掉。反之說(shuō)明不是垃圾,需要將其從緩沖區(qū)移出去。具體的過(guò)程如下:

(1) 從緩沖區(qū)鏈表的 roots 開(kāi)始遍歷,把當(dāng)前 value 標(biāo)為灰色 (zend_refcounted_h.gc_info 置為 GC_GREY),然后對(duì)當(dāng)前 value 的成員進(jìn)行深度優(yōu)先遍歷,把成員 value 的 refcount 減 1,并且也標(biāo)為灰色;

(2) 重復(fù)遍歷緩沖區(qū)鏈表,檢查當(dāng)前 value 引用是否為 0,為 0 則表示確實(shí)是垃圾,把它標(biāo)為白色 (GC_WHITE),如果不為 0 則排除了引用全部來(lái)自自身成員的可能,表示還有外部的引用,并不是垃圾,這時(shí)候因?yàn)椴襟E (1) 對(duì)成員進(jìn)行了 refcount 減 1 操作,需要再還原回去,對(duì)所有成員進(jìn)行深度遍歷,把成員 refcount 加 1,同時(shí)標(biāo)為黑色;

(3) 再次遍歷緩沖區(qū)鏈表,將非 GC_WHITE 的節(jié)點(diǎn)從 roots 鏈表中移出,最終 roots 鏈表中全部為真正的垃圾,最后將這些垃圾清除。

到此,相信大家對(duì)“php中g(shù)c指的是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)
推薦閱讀:
  1. PHP的GC機(jī)制
  2. php gc

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI