PHP垃圾回收機制收集

PHP進行內存管理的核心算法一共兩項:一是引用計數,二是寫時拷貝,請(please)理(bei)解(song)

1.引用計數

使用的是“引用計數”方式進行回收。
簡單地理解的話,就是每個分配的內存區域都有一個計數器,記錄有多少個變量指針指向這片內存。當指向該片內存的指針數量爲0,那麼該片內存區域就可以被回收。
引用計數計數簡單,強大,但是有一個致命的缺陷,就是環狀引用。
code:
<?php
$a = []; 
$a[] = &$a; 
unset($a); 


變量$a引用了自己,形成一個環。$a被unset,但由於存在環狀引用,因此$a之前指向的內存的引用計數爲1,因此該內存區域不會被垃圾回收機制回收。
 
PHP5.3針對這個重大的缺陷做了優化。雖然其基礎仍然是引用計數,但是在做了一些改良,能夠將環狀引用導致的內存泄露控制在一定的規模以內。
當然,這並不是說你可以隨便濫用內存,編寫代碼時仍然要小心爲上!//this is the key point!!
 
其他要點:
1.PHP腳本運行完畢,該腳本申請的所有內存空間都會釋放,不管是否存在環狀引用。因此環狀引用內存泄露的問題一般隻影響長時間運行的程序腳本。 
2.垃圾回收機制需要滿足一定的條件纔會執行。因此unset後,系統並不一定會立即回收垃圾。
3.unset的作用。
“unset只是斷開一個變量到一塊內存區域的連接,同時將該內存區域的引用計數-1”。也就是說,如果有一個以上的變量指向同一個內存區域,或者存在環狀引用,那麼unset不會使內存區域釋放。斷開也說明unset並不會直接刪除內存區域,而只是改變其引用計數而已。
4.$xx=null的作用。
“$a = null 是直接將$a 指向的數據結構置空,同時將其引用計數歸0”。根據我對這個定義的理解,=null操作可以立即釋放掉內存空間!因此很多PHP技巧中不厭其煩地對我們說,先將變量設爲null,再unset。理解其深層原理後,我才徹底理解了這樣做的原因!=null纔是王道!

2.寫時拷貝

即:變量的普通賦值與引用賦值

兩者的區別:

https://blog.csdn.net/william_n/article/details/93601962

 

<?php
// 先不要問爲什麼非要加mt_rand,不然,絕筆說不過來了,到處都是坑
$a = 'hello'.mt_rand( 1, 1000 );
$b = $a;
$a = 123;
echo $b.PHP_EOL;
// 運行結果,不用我說吧,腳趾頭都知道是'hello'.mt_rand( 1, 1000 )的結果,絕對不可能是123。

其實,當你把$a賦值給$b的時候,$a的值並沒有真的複製了一份,這樣是對內存的極度不尊重,也是對時間複雜度的極度不尊重,計算機僅僅是將$b指向了$a的值而已,這就叫多快好省。
那麼,什麼時候真正的發生複製呢?就是當我們修改$a的值爲123的時候,這個時候就不得已進行復制,避免$b的值和$a的一樣。

 

 

Q: 什麼樣的情況會導致zend_value的refcount不爲0,但是這個zend_value卻是個垃圾呢?

A: PHP7種兩種情況:

  1. 數組:數組的某個成員使用&引用自己

  2. 對象:對象的某個成員引用對象自己

    請理(bei)解(song),一般面試,你能回答到這一步,已經非常屌了!

3. 垃圾回收函數  //使用哪些函數可以進行垃圾回收

 

4.資源參考:

https://www.cnblogs.com/wangzhaobo/articles/9591551.html   //PHP的垃圾回收機制以及大概實現  寫得不錯!

https://www.cnblogs.com/zhangyuhang3/p/6873619.html   //PHP垃圾回收機制理解  //也不錯

 

後續補充... 

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