站長資訊網
        最全最豐富的資訊網站

        十分鐘搞清php垃圾回收原理

        十分鐘搞清php垃圾回收原理

        php垃圾回收機制,對于PHPer來說是一個不陌生但是又不是很熟悉的內容。那么php是怎么實現對不需要的內存進行回收的呢?

        php變量的內存存儲結構:

        首先還是需要了解下基礎知識,便于垃圾回收原理內容的理解。大家都知道php是由C編寫而成的,所以php變量的內部存儲結構也會和C語言相關,即zval的結構體:

        struct _zval_struct {     union {         long lval;         double dval;         struct {             char *val;             int len;         } str;         HashTable *ht;         zend_object_value obj;     } value;                    //變量value值     zend_uint refcount__gc;   //引用計數內存中使用次數,為0刪除該變量     zend_uchar type;           //變量類型     zend_uchar is_ref__gc;    //區分是否是引用變量 };

        從上面結構體內容可以看出每一個php變量都會由變量類型、value值、引用計數次數和是否是引用變量四部分組成

        注:上面zval結構體是php5.3版本之后的結構,php5.3之前因為沒有引入新的垃圾回收機制,即GC,所以命名也沒有_gc;而php7版本之后由于性能問題所以改寫了zval結構,這里不再表述。

        引用計數原理

        了解了php變量的內部存儲結構之后,我們再了解下php變量賦值相關的原理和早期垃圾回收機制

        變量容器

        非array和object變量

        每次將常量賦值給一個變量時,都會產生一個變量容器。

        舉例:

        $a = '許錚的技術成長之路'; xdebug_debug_zval('a')

        結果:

        a: (refcount=1, is_ref=0)='許錚的技術成長之路'

        array和object變量

        會產生元素個數+1的變量容器

        舉例:

        $b = [ 'name' => '許錚的技術成長之路', 'number' => 3 ]; xdebug_debug_zval('b')

        結果:

        b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='許錚的技術成長之路',  'number' => (refcount=1, is_ref=0)=3)

        賦值原理(寫時復制技術)

        了解了常量賦值之后,接下來我們從內存角度思考變量之間的賦值

        舉例:

        $a = [ 'name' => '許錚的技術成長之路', 'number' => 3 ]; //創建一個變量容器,變量a指向給變量容器,a的ref_count為1 $b = $a; //變量b也指向變量a指向的變量容器,a和b的ref_count為2 xdebug_debug_zval('a', 'b'); $b['name'] = '許錚的技術成長之路1';//變量b的其中一個元素發生改變,此時會復制出一個新的變量容器, 變量b重新指向新的變量容器,a和b的ref_count變成1 xdebug_debug_zval('a', 'b');

        結果:

        a: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='許錚的技術成長之路', 'number' => (refcount=1, is_ref=0)=3) b: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='許錚的技術成長之路', 'number' => (refcount=1, is_ref=0)=3) a: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='許錚的技術成長之路', 'number' => (refcount=1, is_ref=0)=3) b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='許錚的技術成長之路1', 'number' => (refcount=1, is_ref=0)=3)

        所以,當變量a賦值給變量b的時候,并沒有立刻生成一個新的變量容器,而是將變量b指向了變量a指向的變量容器,即內存"共享";而當變量b其中一個元素發生改變時,才會真正發生變量容器復制,這就是寫時復制技術

        引用計數清0

        當變量容器的ref_count計數清0時,表示該變量容器就會被銷毀,實現了內存回收,這也是php5.3版本之前的垃圾回收機制

        舉例:

        $a = "許錚的技術成長之路"; $b = $a; xdebug_debug_zval('a'); unset($b); xdebug_debug_zval('a');

        結果:

        a: (refcount=2, is_ref=0)='許錚的技術成長之路' a: (refcount=1, is_ref=0)='許錚的技術成長之路'

        循環引用引發的內存泄漏問題:

        但是php5.3版本之前的垃圾回收機制存在一個漏洞,即當數組或對象內部子元素引用其父元素,而此時如果發生了刪除其父元素的情況,此變量容器并不會被刪除,因為其子元素還在指向該變量容器,但是由于所有作用域內都沒有指向該變量容器的符號,所以無法被清除,因此會發生內存泄漏,直到該腳本執行結束

        舉例:

        $a = array( 'one' ); $a[] = &$a; xdebug_debug_zval( 'a' );

        由于該示例不好輸出結果,用圖表示,如圖:

        十分鐘搞清php垃圾回收原理

        舉例:

        unset($a); xdebug_debug_zval('a');

        如圖:

        十分鐘搞清php垃圾回收原理

        新的垃圾回收機制:

        php5.3版本之后引入根緩沖機制,即php啟動時默認設置指定zval數量的根緩沖區(默認是10000),當php發現有存在循環引用的zval時,就會把其投入到根緩沖區,當根緩沖區達到配置文件中的指定數量(默認是10000)后,就會進行垃圾回收,以此解決循環引用導致的內存泄漏問題

        確認為垃圾的準則

        1、如果引用計數減少到零,所在變量容器將被清除(free),不屬于垃圾
        2、如果一個zval 的引用計數減少后還大于0,那么它會進入垃圾周期。其次,在一個垃圾周期中,通過檢查引用計數是否減1,并且檢查哪些變量容器的引用次數是零,來發現哪部分是垃圾。

        總結

        垃圾回收機制:
        1、以php的引用計數機制為基礎(php5.3以前只有該機制)
        2、同時使用根緩沖區機制,當php發現有存在循環引用的zval時,就會把其投入到根緩沖區,當根緩沖區達到配置文件中的指定數量后,就會進行垃圾回收,以此解決循環引用導致的內存泄漏問題(php5.3開始引入該機制)

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 久久久不卡国产精品一区二区| 国产在线不卡午夜精品2021| 国产精品欧美一区二区三区不卡 | 国产69精品久久久久99尤物| 国内精品久久人妻互换| 久久亚洲精品无码播放| AAA级久久久精品无码区| 99久久这里只有精品| 亚洲∧v久久久无码精品 | 国产精品亚洲w码日韩中文| 精品国产网红福利在线观看| 蜜国产精品jk白丝AV网站| 欧美人与性动交α欧美精品成人色XXXX视频| 精品久久久久久综合日本| 精品国产sm捆绑最大网免费站 | 久久精品国产99久久丝袜| 91热成人精品国产免费| 久久精品国产影库免费看| 99精品一区二区三区无码吞精| 久久精品国产99久久无毒不卡 | 国产精品久久久久久| 精品爆乳一区二区三区无码av| 亚洲精品白浆高清久久久久久| 日本精品少妇一区二区三区| 成人国产精品动漫欧美一区| 丝袜美腿国产精品视频一区| 你懂的国产精品| 热久久国产精品| 2021年精品国产福利在线| 亚洲精品无码不卡| 98香蕉草草视频在线精品看| 91精品国产色综久久| 91精品免费久久久久久久久| 国产高清日韩精品欧美激情| 国产2021久久精品| 国产精品无码不卡一区二区三区| wwwvr高清亚洲精品二区| 国产日韩久久久精品影院首页| 精品人妻V?出轨中文字幕 | 精品国产一级在线观看| 精品一区二区三区四区在线|