最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析PHP7 的垃圾回收機制

 更新時間:2019年09月06日 09:17:38   作者:JeffreyC  
垃圾回收機制是一種動態(tài)存儲分配方案。它會自動釋放程序不再需要的已分配的內(nèi)存塊。 這篇文章主要介紹了PHP7 的垃圾回收機制,需要的朋友可以參考下

垃圾回收機制

垃圾回收機制是一種動態(tài)存儲分配方案。它會自動釋放程序不再需要的已分配的內(nèi)存塊。 自動回收內(nèi)存的過程叫垃圾收集。垃圾回收機制可以讓程序員不必過分關(guān)心程序內(nèi)存分配,從而將更多的精力投入到業(yè)務(wù)邏輯。 在現(xiàn)在的流行各種語言當中,垃圾回收機制是新一代語言所共有的特征。

垃圾的產(chǎn)生

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

不過有一種問題是這個機制無法解決的,就是循環(huán)引用的問題。

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

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

舉個例子:

// 當進行如下賦值操作時
$a = 'hello'; // $a -> zend_string
$b = $a; // $b,$a -> zend_string
$c = &$b; // $c,$b -> zval(type = IS_REFERENCE, refcount = 2) -> zend_string


最終會變成如下這樣:

 

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

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

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

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

具體如下如所示:

 

當 unset 之后就變成下圖這樣:

 

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

回收過程

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

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的類型, 與zval.u1.type一致
      zend_uchar  flags, 
      uint16_t   gc_info // GC信息,記錄在 gc 池中的位置和顏色,垃圾回收的過程會用到
    } v;
    uint32_t type_info;
  } u;
} zend_refcounted_h;

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

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

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

(2) 重復(fù)遍歷緩沖區(qū)鏈表,檢查當前 value 引用是否為 0,為 0 則表示確實是垃圾,把它標為白色(GC_WHITE),如果不為 0 則排除了引用全部來自自身成員的可能,表示還有外部的引用,并不是垃圾,這時候因為步驟(1)對成員進行了 refcount 減 1 操作,需要再還原回去,對所有成員進行深度遍歷,把成員 refcount 加 1,同時標為黑色;

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

總結(jié)

以上所述是小編給大家介紹的PHP7 的垃圾回收機制,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

相關(guān)文章

  • CI(CodeIgniter)簡單統(tǒng)計訪問人數(shù)實現(xiàn)方法

    CI(CodeIgniter)簡單統(tǒng)計訪問人數(shù)實現(xiàn)方法

    這篇文章主要介紹了CI(CodeIgniter)簡單統(tǒng)計訪問人數(shù)實現(xiàn)方法,這里使用TXT文本文件簡單演示了CodeIgniter框架記錄訪問人數(shù)的實現(xiàn)技巧,需要的朋友可以參考下
    2016-01-01
  • 在 Laravel 中動態(tài)隱藏 API 字段的方法

    在 Laravel 中動態(tài)隱藏 API 字段的方法

    這篇文章主要介紹了在 Laravel 中動態(tài)隱藏 API 字段的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-10-10
  • php7下的filesize函數(shù)

    php7下的filesize函數(shù)

    在php下filesize是用來計算文件大小的函數(shù),我們可以通過filesize(‘file’)的形式來確定一個文件的字節(jié)大小,通過/1024來精確KB,GB等單位。這篇文章主要介紹了php7下的filesize,需要的朋友可以參考下
    2019-09-09
  • Laravel實現(xiàn)表單提交

    Laravel實現(xiàn)表單提交

    本文給大家分享的是在使用laravel過程中如何實現(xiàn)表單提交的一個簡單示例,非常簡單,這里推薦給學(xué)習(xí)laravel的小伙伴
    2017-05-05
  • 變量在 PHP7 內(nèi)部的實現(xiàn)(一)

    變量在 PHP7 內(nèi)部的實現(xiàn)(一)

    這篇文章主要介紹了變量在 PHP7 內(nèi)部的實現(xiàn)(一)的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • Laravel 5框架學(xué)習(xí)之子視圖和表單復(fù)用

    Laravel 5框架學(xué)習(xí)之子視圖和表單復(fù)用

    本文給大家主要介紹的是Laravel5框架中的子視圖以及表單復(fù)用的用法,十分的細致全面,對于大家熟練掌握Laravel5框架非常有幫助,有需要的小伙伴可以參考下
    2015-04-04
  • php分享朋友圈的實現(xiàn)代碼

    php分享朋友圈的實現(xiàn)代碼

    這篇文章主要為大家詳細介紹了php分享朋友圈的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • ThinkPHP5.0框架結(jié)合Swoole開發(fā)實現(xiàn)WebSocket在線聊天案例詳解

    ThinkPHP5.0框架結(jié)合Swoole開發(fā)實現(xiàn)WebSocket在線聊天案例詳解

    這篇文章主要介紹了ThinkPHP5.0框架結(jié)合Swoole開發(fā)實現(xiàn)WebSocket在線聊天,結(jié)合完整案例形式詳細分析了thinkPHP5擴展Swoole實現(xiàn)WebSocket在線聊天相關(guān)步驟、操作技巧與注意事項,需要的朋友可以參考下
    2019-04-04
  • PHP判斷是否是微信打開還是瀏覽器打開的方法

    PHP判斷是否是微信打開還是瀏覽器打開的方法

    今天小編就為大家分享一篇關(guān)于PHP判斷是否是微信打開還是瀏覽器打開的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • PHP插入排序?qū)崿F(xiàn)代碼

    PHP插入排序?qū)崿F(xiàn)代碼

    插入排序的基本操作就是將一個數(shù)據(jù)插入到已經(jīng)排好序的有序數(shù)據(jù)中,從而得到一個新的、個數(shù)加一的有序數(shù)據(jù)。
    2013-04-04

最新評論

丰都县| 蓬溪县| 澄迈县| 吉林市| 吴江市| 集贤县| 乌恰县| 天全县| 二连浩特市| 贵港市| 翁牛特旗| 柏乡县| 泸定县| 公主岭市| 宁夏| 渑池县| 谢通门县| 隆回县| 垫江县| 久治县| 黔东| 固阳县| 永丰县| 太保市| 静海县| 陕西省| 荆州市| 溧水县| 壶关县| 罗平县| 永德县| 临泽县| 德江县| 开封市| 土默特左旗| 闸北区| 辽源市| 河源市| 株洲市| 繁昌县| 石河子市|