首頁  >  文章  >  後端開發  >  php回收週期的介紹

php回收週期的介紹

不言
不言轉載
2019-02-28 14:29:182216瀏覽

這篇文章帶給大家的內容是關於php回收週期的介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

以下程序僅對陣列和物件類型起作用。

傳統上,像是以前的 php 所用的引用計數記憶體機制,無法處理循環的引用記憶體洩漏。然而 5.3.0 PHP 使用文章» 引用計數系統中的同步週期回收(Concurrent Cycle Collection in Reference Counted Systems)中的同步演算法,來處理這個記憶體洩漏問題。

對演算法的完全說明有點超出這部分內容的範圍,將只介紹其中基礎部分。首先,我們先要建立一些基本規則,如果一個引用計數增加,它將繼續被使用,當然就不再在垃圾中。如果引用計數減少到零,所在變數容器將被清除(free)。是說,僅僅在引用計數減少到非零值時,才會產生垃圾週期(garbage cycle)。其次,在一個垃圾週期中,透過檢查引用計數是否減1,並且檢查哪些變數容器的引用次數是零,來發現哪一部分是垃圾。

php回收週期的介紹

為避免必須檢查所有參考計數可能減少的垃圾週期,這個演算法把所有可能根(possible roots 都是zval變數容器),放在根緩衝區(root buffer)中(用紫色來標記,稱為疑似垃圾),這樣可以同時確保每個可能的垃圾根(possible garbage root)在緩衝區中只出現一次。僅在根緩衝區滿了時,才對緩衝區內部所有不同的變數容器執行垃圾回收操作。看上圖的步驟 A。

在步驟 B 中,模擬刪除每個紫色變數。模擬刪除時可能將不是紫色的普通變數引用數減」1″,如果某個普通變數引用計數變成0了,就對這個普通變數再做一次模擬刪除。每個變數只能被模擬刪除一次,模擬刪除後標記為灰(原文說確保不會對同一個變數容器減兩次”1″,不對的吧)。

在步驟 C 中,模擬恢復每個紫色變數。恢復是有條件的,當變數的引用計數大於0時才對其做模擬恢復。同樣每個變數只能恢復一次,恢復後標示為黑,基本上就是步驟 B 的逆運算。這樣剩下的一堆沒能恢復的就是該刪除的藍色節點了,在步驟 D 中遍歷出來真的刪除掉。

演算法中都是模擬刪除、模擬恢復、真的刪除,都使用簡單的遍歷即可(最典型的深搜遍歷)。複雜度為執行模擬操作的節點數呈正相關,不只是紫色的那些疑似垃圾變數。

現在,你已經對這個演算法有了基本了解,我們回頭來看這個如何與PHP整合。預設的,PHP的垃圾回收機制是打開的,然後有個 php.ini 設定允許你修改它:zend.enable_gc 。

當垃圾回收機制開啟時,每當根快取區存滿時,就會執行上面描述的循環查找演算法。根快取區有固定的大小,可存10,000個可能根,當然你可以透過修改PHP原始碼檔案Zend/zend_gc.c中的常數GC_ROOT_BUFFER_MAX_ENTRIES,然後重新編譯PHP,來修改這個10,000值。當垃圾回收機制關閉時,循環查找演算法永不執行,然而,可能根將一直存在根緩衝區中,不管在配置中垃圾回收機制是否啟動。

當垃圾回收機制關閉時,如果根緩衝區存滿了可能根,更多的可能根顯然不會被記錄。那些沒被記錄的可能根,將不會被這個演算法分析處理。如果他們是循環引用週期的一部分,將永遠不能被清除進而導致記憶體洩漏。

即使在垃圾回收機制不可用時,可能根也被記錄的原因是,相對於每次找到可能根後檢查垃圾回收機制是否打開而言,記錄可能根的操作更快。不過垃圾回收和分析機製本身要耗不少時間。

除了修改配置zend.enable_gc ,也能透過分別呼叫gc_enable() 和 gc_disable()函數來開啟和關閉垃圾回收機制。呼叫這些函數,與修改配置項來開啟或關閉垃圾回收機制的效果是一樣的。即使在可能根緩衝區還沒滿時,也能強制執行週期回收。你能呼叫gc_collect_cycles()函數達到這個目的。這個函數將會傳回使用這個演算法回收的周期數。

允許打開和關閉垃圾回收機制並且允許自主的初始化的原因,是由於你的應用程式的某一部分可能是高時效性的。在這種情況下,你可能不想使用垃圾回收機制。當然,對你的應用程式的某部分關閉垃圾回收機制,是在冒著可能記憶體洩漏的風險,因為一些可能根也許存不進有限的根緩衝區。因此,就在你呼叫gc_disable()函數釋放記憶體之前,先呼叫gc_collect_cycles()函數可能比較明智。因為這將清除已存放在根緩衝區中的所有可能根,然後在垃圾回收機制被關閉時,可留下空緩衝區以有更多空間存儲可能根。


以上是php回收週期的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除