摘要:垃圾回收所謂垃圾就是指通過循環引用自己引用自己,目前只在類型中有出現的形式而導致永遠不為。當出現垃圾之后,的引擎有對應的垃圾回收機制。觸發這個機制的時機是每次出現減少時候。
自嘲)。。。。。2333,我覺得這是因為在php語言層面就幫我們解決了內存回收的問題,但這讓我在和java大牛們吹牛逼的時候,聽到什么內存泄露。。。。(納尼,我tmd怎么從來沒遇見過)一臉懵逼。
本人小菜,如果下面所寫有什么錯誤的地方,請大神指出,并且下文,很多都是讀書+看源碼之后自己的總結。
前言在上一篇中我淺談的PHP中的基本數據容器,zend_value,zval
實際存儲數據的并不全是zend_value,還有一個被zend_value通過指針指向的具體的數據存儲結構體,如_zend_array,_zend_string
struct _zend_string { zend_refcounted_h gc; zend_ulong h; /* hash value */ size_t len; char val[1]; };
struct _zend_array { zend_refcounted_h gc; union { struct { ZEND_ENDIAN_LOHI_4( zend_uchar flags, zend_uchar nApplyCount, zend_uchar nIteratorsCount, zend_uchar consistency) } v; uint32_t flags; } u; uint32_t nTableMask; Bucket *arData; uint32_t nNumUsed; uint32_t nNumOfElements; uint32_t nTableSize; uint32_t nInternalPointer; zend_long nNextFreeElement; dtor_func_t pDestructor; };
注意每個結構體中都有一個名為gc的變量,這個變量其實就是 zend_refcounted_h 引用計數
內存回收的兩種情況
正常的變量在生命周期完成之后的回收。
這種情況也就是說當zend_value中refCount==0的時候,這時候屬于正常的內存回收。
垃圾回收
所謂垃圾: 就是指通過循環引用(自己引用自己,目前只在array,object類型中有出現)的形式而導致refcount永遠不為0。這種情況下,如果不處理,但是這些內存無法釋放,到時內存泄露
代碼如下:
$a = array(1,2 ); xdebug_debug_zval("a"); $a[] = &$a; xdebug_debug_zval("a"); $b=$a; unset($a); xdebug_debug_zval("a"); xdebug_debug_zval("b");
結果如下
a: (refcount=1, is_ref=0) array (size=2) 0 => (refcount=0, is_ref=0)int 1 1 => (refcount=0, is_ref=0)int 2 a: (refcount=2, is_ref=1) array (size=3) 0 => (refcount=0, is_ref=0)int 1 1 => (refcount=0, is_ref=0)int 2 2 => (refcount=2, is_ref=1) &array< a: (refcount=0, is_ref=0)*uninitialized* b: (refcount=2, is_ref=0) array (size=3) 0 => (refcount=0, is_ref=0)int 1 1 => (refcount=0, is_ref=0)int 2 2 => (refcount=1, is_ref=1) &array<
按照正常邏輯,當unset($a),之后,其對應的zeng_value的refCount=1,is_ref=0,但是實際上它卻是等于refCount=2,is_ref=0, 這就導致,就算是unset($b),之后,refCount=1,is_ref=0,這種結果,像上面當refCount=0后正常回收內存。
![圖片上傳中...]
這就是 垃圾。
當出現垃圾之后,php的zend引擎有對應的垃圾回收機制。
其實這種機制的原理就是 :
(1).將這些垃圾放入buffer中。 (2).當buffer到達一定數量之后,啟動對所有垃圾的value自身的refCount-1,并將zend_refcounted中的gc_info變量置為GC_GRAY
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;
(3).遍歷當前buffer,當refCount=0是則表示當前的這個value的確是個垃圾,則將zend_refcounted中的gc_info變量置為GC_WHITE。然后因為所有的value中都減1,所以再次遍歷,將那些減一后refcount !=0 的value+1,然后將zend_refcounted中的gc_info變量置為GC_BLACK (4).最后遍歷buffer,將buffer中的value的zend_refcounted中的gc_info為GC_WHITE刪除 講完GC垃圾回收算法的原理,貌似我還沒有講在什么時候會觸發將這個**可能**的垃圾放入buffer。。。。。。 ***觸發這個機制的時機是每次出現refCount減少時候。***
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28469.html
摘要:所有這些類型,在內部統一用一個叫做的結構表示,在源代碼中這個結構名稱為。的具體定義在源代碼的文件中,下面是相關代碼的摘錄。 【轉】淺談PHP5中垃圾回收算法(Garbage Collection)的演化 前言 PHP是一門托管型語言,在PHP編程中程序員不需要手工處理內存資源的分配與釋放(使用C編寫PHP或Zend擴展除外),這就意味著PHP本身實現了垃圾回收機制(Garbage C...
摘要:本書的地址篇收集了一些常見的基礎進階面試題,基礎的面試題不再作答。如何實現持久化持久化,將在內存中的的狀態保存到硬盤中,相當于備份數據庫狀態。相當于備份數據庫接收到的命令,所有被寫入的命令都是以的協議格式來保存的。 本書的 GitHub 地址:https://github.com/todayqq/PH... PHP 篇收集了一些常見的基礎、進階面試題,基礎的面試題不再作答。 基礎篇 ...
摘要:插入一個元素時先將元素按先后順序插入數組,位置是,再根據的哈希值映射到散列表中的某個位置,將存入這個位置查找時先在散列表中映射到,得到在數組的位置,再從數組中取出元素。目前只有兩種類型會使用這種機制。 1.變量結構 typedef struct _zval_struct zval; typedef union _zend_value { zend_long ...
摘要:本文主要是針對,的話可以移步到慶哥的博客看,還有就是小菜我讀的是內核剖析這本書。接下來我會使用到來調試源碼本文有參照博客中的部分內容以及代碼。 前言 工作+實習快一年了,搞php后端開發,一直很迷茫怎么提高自己,就先從php源碼開始吧,本人比較菜,本文章寫的比較趕時間,所以有什么錯誤或者漏掉的地方,望各位大神指正,多交流才能成長嘛,嘿嘿。本文主要是針對php7,php5的話可以移步到慶...
摘要:前言垃圾回收機制在工作中很少碰到,看到阮一峰的書中有寫,記錄下。垃圾回收機制與垃圾回收機制只考慮對象的強引用垃圾回收機制依賴引用計數,當計數為,則自動回收該對象占用的內存。里面的引用,都不計入垃圾回收機制,所以就不存在這個問題。 showImg(https://segmentfault.com/img/remote/1460000019752744); 前言:垃圾回收機制在工作中很少碰...
閱讀 2972·2021-09-22 15:18
閱讀 3395·2019-08-30 15:54
閱讀 3274·2019-08-30 15:53
閱讀 589·2019-08-30 14:12
閱讀 814·2019-08-29 17:01
閱讀 2198·2019-08-29 14:04
閱讀 1379·2019-08-29 13:09
閱讀 862·2019-08-26 17:40