垃圾收集器(GC)是 PHP 中的內部記憶體管理系統,但有一些微妙之處需要理解。
GC 自動化記憶體管理,消除了透過手動任務處理記憶體的麻煩(這會很乏味)。
這使得開發人員可以專注於他們的業務邏輯,而不必過度擔心「記憶體不足」錯誤。
當然,這不是魔法。
釋放不再需要的物件可以防止記憶體洩漏。
GC 使用計數機制來決定要丟棄的元素。如果沒有引用指向特定物件(即 $counter = 0),則該物件有資格進行清理。
它運作得很好,但有些引用可能有問題:
class A { public $b; } class B { public $a; } $a = new A(); $b = new B(); $a->b = $b; $b->a = $a; unset($a); unset($b);
在這種設計不佳的情況下,即使我們取消設定 $a 和 $b,PHP 也不會釋放內存,因為它們相互引用,導致 PHP 認為它們仍在使用中。
幸運的是,還有另一種稱為循環收集器的機制:
gc_collect_cycles();
粗略地說,收集器會遍歷所有引用並應用一種演算法來標記正在使用的對象,從而顯示要收集的對象(未標記的對象)。
但是,PHP 不會觸發自動循環收集,直到達到具有潛在循環引用的 10,000 個物件 的閾值。
再次強調,這不是魔法,因此只有在少數情況下才必須呼叫 gc_collect_cycles()。
糟糕的設計可能會導致物件之間的關係過於複雜,從而導致更多的引用和更頻繁的垃圾回收。
每個引用計數物件都需要額外的儲存空間來儲存其引用計數。
資料來源:維基百科 - 引用計數
與記憶體清理操作相關的開銷會顯著影響全域效能,並最終增加特定場景中的執行時間。
10 年前,Composer 僅透過使用 gc_disable() 函數就獲得了巨大的效能提升。
來源:Composer - 停用 GC
確實,PHP 7 大大改進了 GC,所以現在已經不是 2014 年的樣子了。
此外,PHP 8 版本改進了記憶體分配策略,並添加了更多有關 GC 操作的有用統計信息,以便更好地監控(8.3 中的 gc_status())。
大多數PHP應用程式都是請求驅動的,請求結束時記憶體會自動清除。
再說一遍,這很酷,但並不神奇。非同步請求和長期存在的物件/守護程式會發生什麼?
您可能會在某些時候遇到記憶體洩漏。
此時,你可能還看不出 PHP 的 GC 與其他語言有何不同。
大多數時候,其他語言不依賴引用計數來收集垃圾,或可能使用不同的實作。
例如,許多使用追蹤演算法,該演算法也標記未使用的對象,但不會增量操作。這是一個圖的遍歷。
此外,某些語言不允許這種直接控制(例如,運行時開/關)。
像往常一樣,有一些優點和不方便,所以你可能會看到一些混合方法。
您可以利用內建的 gc_* 幫助程式。
例如:
這些函數有助於除錯或微調垃圾收集必要時。
您可以閱讀這篇文章以獲得更多見解:
PHP 7.4 引入了弱引用,PHP 8 引入了弱映射。
弱映射可以被描述為弱引用的集合。
此資料結構是一種多功能鍵值存儲,可幫助 PHP 追蹤項目,而不會造成混亂或消耗過多空間。
您可能會將其視為臨時存儲,當不再需要時將立即清除,因為沒有[強]引用可以阻止垃圾收集:
class A { public $b; } class B { public $a; } $a = new A(); $b = new B(); $a->b = $b; $b->a = $a; unset($a); unset($b);
對於大多數用法,您不必擔心記憶體管理,因為 PHP 已經處理了它。
但是,由於現代堆疊使用長壽命對象,因此您需要監視應用程式是否存在潛在的記憶體洩漏。
如果遇到問題,您可能需要最佳化程式碼和/或直接與 GC 互動。
以上是PHP:用簡單的話解釋垃圾收集器的詳細內容。更多資訊請關注PHP中文網其他相關文章!