首頁 >後端開發 >php教程 >PHP:用簡單的話解釋垃圾收集器

PHP:用簡單的話解釋垃圾收集器

Linda Hamilton
Linda Hamilton原創
2024-11-29 00:46:11808瀏覽

垃圾收集器(GC)是 PHP 中的內部記憶體管理系統,但有一些微妙之處需要理解。

?為什麼 GC 會存在?

GC 自動化記憶體管理,消除了透過手動任務處理記憶體的麻煩(這會很乏味)。

這使得開發人員可以專注於他們的業務邏輯,而不必過度擔心「記憶體不足」錯誤。

當然,這不是魔法。

?簡而言之 10,000 個對象

釋放不再需要的物件可以防止記憶體洩漏

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 有何不同?

此時,你可能還看不出 PHP 的 GC 與其他語言有何不同。

大多數時候,其他語言不依賴引用計數來收集垃圾,或可能使用不同的實作。

例如,許多使用追蹤演算法,該演算法也標記未使用的對象,但不會增量操作。這是一個圖的遍歷。

此外,某些語言不允許這種直接控制(例如,運行時開/關)。

像往常一樣,有一些優點和不方便,所以你可能會看到一些混合方法。

?‍?與 PHP 的 GC 交互

您可以利用內建的 gc_* 幫助程式。

例如:

  • gc_collect_cycles 手動觸發垃圾收集
  • gc_status() 給出當前狀態
  • gc_disable() 停用它
  • gc_enable() 啟用它

這些函數有助於除錯或微調垃圾收集必要時

?了解記憶體錯誤

您可以閱讀這篇文章以獲得更多見解:

PHP: The Garbage Collector explained with simple words

PHP:記憶體錯誤

spO0q ? ・ 2023 年 5 月 24 日

#php #初學者 #程式設計

?弱地圖可以拯救嗎?

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);

✅ 優點

  • 非常簡單
  • 非常適合緩存或記憶(例如,昂貴的計算)

❌ 缺點

  • 雖然鍵(物件)不會阻止垃圾回收,但值可以,因此術語「任意值」可能會產生誤導(僅使用簡單資料類型作為值)
  • 有價值的用例是有限的

?最佳化程式碼

  • 利用減少相互依賴性的設計模式
  • 使用依賴注入
  • 不要將太大的資料集載入到記憶體中,並使用集合和產生器而不是巨大的陣列
  • 監控記憶體使用量
  • 使用指標分析您的程式碼
  • 謹慎使用 gc_enable()、gc_disable() 和 gc_collect_cycles()

包起來

對於大多數用法,您不必擔心記憶體管理,因為 PHP 已經處理了它。

但是,由於現代堆疊使用長壽命對象,因此您需要監視應用程式是否存在潛在的記憶體洩漏。

如果遇到問題,您可能需要最佳化程式碼和/或直接與 GC 互動。

以上是PHP:用簡單的話解釋垃圾收集器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn