1 引用計數
引用計數是指在value中增加乙個字段refcount
記錄指向當前value的數量,變數複製、函式傳參時並不直接硬拷貝乙份value資料,而是將refcount++
,變數銷毀時將refcount--
,等到refcount
減為0時表示已經沒有變數引用這個value,將它銷毀即可。
儲存結構如下:
1 typedef struct_zend_refcounted_h v;
10uint32_t type_info;
11} u;
12 } zend_refcounted_h;
引用計數的資訊位於給具體value結構的gc中,例如在字串變數中:
1 typedef struct_zend_string zend_string;
2struct
_zend_string ;
2 寫時複製
引用計數,多個變數可能指向同乙個value,然後通過refcount統計引用數,這時候如果其中乙個變數試圖更改value的內容則會重新拷貝乙份value修改,同時斷開舊的指向,寫時複製的機制在計算機系統中有非常廣的應用,它只有在必要的時候(寫)才會發生硬拷貝,可以很好的提高效率
不是所有型別都可以copy的,比如物件、資源,實時上只有string、array兩種支援,與引用計數相同,也是通過zval.u1.type_flag
標識value是否可複製的
3 變數**
php變數的**主要有兩種:主動銷毀、自動銷毀。
主動銷毀指的就是 unset。
自動銷毀就是php的自動管理機制,在return時減掉區域性變數的refcount,即使沒有顯式的return,php也會自動給加上這個操作,另外乙個就是寫時複製時會斷開原來value的指向,這時候也會檢查斷開後舊value的refcount。
4
垃圾**
php變數的**是根據refcount實現的,當unset、return時會將變數的引用計數減掉,如果refcount減到0則直接釋放value,這是變數的簡單gc過程
1$a = [1];
2$a = &$a;3
unset($a);
可以看到,unset($a)
之後由於陣列中有子元素指向$a
,所以refcount > 0
,無法通過簡單的gc機制**,這種變數就是垃圾,垃圾**器要處理的就是這種情況,目前垃圾只會出現在array、object兩種型別中,所以只會針對這兩種情況作特殊處理:當銷毀乙個變數時,如果發現減掉refcount後仍然大於0,且型別是is_array、is_object則將此value放入gc可能垃圾雙向鍊錶中,等這個煉表達到一定數量後啟動檢查程式將所有變數檢查一遍,如果確定是垃圾則銷毀釋放。
PHP中session變數的銷毀
1.何為session?2.session變數的銷毀 程式 session unset session destroy session unset 釋放當前在記憶體中已經建立的所有 session變數,但不刪除session檔案以及不釋放對應的session id session destroy 刪...
PHP中session變數的銷毀
1.何為session?2.session變數的銷毀 程式 session unset session destroy session unset 釋放當前在記憶體中已經建立的所有 session變數,但不刪除session檔案以及不釋放對應的session id session destroy 刪...
詳解PHP變數傳值賦值和引用賦值變數銷毀
b 200 var dump a,b int 100 int 200 php中,上面的 變數是怎麼存放的呢?上面的 變動下,將變數b賦值給變數a,會發生什麼?b 200 a b 多了這個 var dump a,b int 200 int 200 問題來了,a b,那麼是將變數a的指標指向了變數b指標...