搜尋
首頁後端開發php教程PHP主|更好地了解PHP的垃圾收集

PHP Master | Better Understanding PHP’s Garbage Collection

時間變遷,術語也隨之改變。如今,我們可能稱之為“PHP 資源回收”,而非“垃圾回收”。這更貼切地反映了其本質:並非簡單丟棄,而是重新利用不再使用的資源。然而,沿用“垃圾回收”這一歷史沿襲下來的名稱更為常見。

核心要點:

  • PHP 的垃圾回收機制分三個層次:作用域結束、引用計數和正式垃圾回收。作用域結束時,函數、腳本或會話中的資源會被清除。引用計數追踪使用某個變量的實體數量,計數為零時,變量被銷毀。 PHP 5.3 引入的正式垃圾回收機制則處理引用計數非零但可進一步遞減的情況。
  • PHP 的垃圾回收機制始終啟用,但可手動控制。可在 php.ini 文件中或使用 gc_enable() 和 gc_disable() 函數在腳本中禁用。 gc_collect_cycles() 函數允許手動啟動垃圾回收,根緩衝區大小可在 PHP 源代碼中修改。
  • 垃圾回收雖然有助於管理內存分配和防止內存洩漏,但其資源密集型特性也會影響性能。因此,應策略性地使用,尤其是在長時間運行的腳本或永不結束的腳本中,垃圾回收對於防止內存洩漏至關重要。
  • 良好的編程實踐有助於優化垃圾回收。這包括盡量減少或消除全局變量,將變量綁定到作用域,並註意數組嵌套或對象引用對象的情況,因為這些情況可能導致內存洩漏,也是正式垃圾回收機制的主要目標。

程序生成的垃圾

程序使用資源,有時是小資源,有時是大資源。例如數據字段。程序可能定義一個數據字段(例如序列號),並在程序中使用。一旦定義,此數據字段將佔用內存空間,可能只有幾字節,但仍然是空間。由於每台機器或編程環境都有有限的可用空間,剩餘空間將減少該字段佔用的空間量。當程序結束時,程序及其占用的任何空間都將消失,可用總空間將恢復到最大大小。但是,如果程序永不結束會發生什麼?我曾經編寫過一些此類程序。它們是美麗的傑作,每當車間裡的其他人注意到我創建了一個時,我總是很高興。沒有什麼比你自己讓一台大型IBM 計算機停機更能體現你的能力了,而周圍的隔間裡,一個人接一個人大聲說:“嘿,系統有什麼問題嗎?”訣竅是第二個或第三個加入,以轉移對你的注意力。但有些程序甚至旨在永遠運行,例如守護進程和其他此類程序。隨著它們的運行,它們產生的垃圾量可能會不斷增長。如果鎖定的資源很大,則會對系統產生真正的負面影響。因此,每種語言都必須有一種方法來清除孤立的資源,使它們可供其他用戶使用,並確保可用系統空間總量保持不變。幸運的是,PHP 採用三層方法進行垃圾清除。

第一層——作用域結束

首先,與大多數語言一樣,每當作用域結束時,該作用域內的所有內容都會被銷毀,任何已分配的資源都會被釋放。作用域可以涵蓋函數、腳本、會話等,當該作用域結束時,它所持有的所有內容也隨之結束。當然,您可以隨時使用 unset() 函數釋放資源。這就是函數和方法如此重要的原因之一,因為它們建立了作用域,規定了特定內存使用何時開始和何時結束,並限制了事物存在的時間。應盡可能使用它們,而不是全局實體。

第二層——引用計數

其次,與大多數腳本語言一樣,PHP 使用稱為引用計數的技術來跟踪有多少實體正在使用給定的變量。當在 PHP 腳本中創建變量時,PHP 會創建一個名為 zval 的小“容器”,該容器由分配給該變量的值加上另外兩條信息組成:is_ref 和 refcount。 zval 容器保存在表中,每個作用域(腳本、函數、方法等)都有一個表。 is_ref 是一個簡單的真/假值,指示變量是否是引用集的一部分,從而幫助 PHP 判斷這是一個簡單變量還是一個引用。 refcount 更有趣,因為它保存一個數值,指示有多少不同的變量正在使用此值。也就是說,如果您定義變量 $dave = 6,則 refcount 將設置為 1。如果我說 $programmer = $dave,則 refcount 將遞增到 2。 PHP 知道不要為值 6 創建第二個 zval;它只是更新已存在的值容器上的計數器。當程序結束時,或者當我們離開函數的作用域時,或者當使用 unset() 時,則此 refcount 將遞減。當 refcount 達到零時,zval 將被銷毀,它所持有的任何內存現在都已釋放。當然,這是一個簡單變量的簡單示例。當您談論數組或對象時,情況要復雜得多,因為將為數組中元素的多個值創建多個 zref,但基本處理過程相同。但是,如果我們在另一個數組中使用數組,這在更複雜的 PHP 腳本中經常發生,則會出現問題。在這種情況下,當設置原始數組值時,數組值的 refcount 設置為 1,然後當數組與另一個數組關聯時,refcount 遞增到 2。如果第二個數組的使用範圍結束,則 refcount 遞減 1。我們現在處於這樣一種情況:值本身不再與任何內容關聯,但表示它的容器 (zval) 的 refcount 仍然大於零。最終結果是,原始數組表示的存儲將不會被釋放,並且該內存量現在無法供任何內容使用。通常,我們認為這種丟失的存儲量很小,但通常並非如此。如今,數組可能是非常大的東西,如果發生這種情況的腳本是守護進程或其他幾乎連續運行的函數,則尤其成問題。在這種情況下,由此產生的“內存洩漏”可能會對性能甚至服務器的操作能力產生災難性的後果。

第三層——正式垃圾回收

顯然,基於引用計數的清除有其局限性,但幸運的是,PHP 5.3 提供了另一個選項來幫助解決這種情況。我們希望垃圾回收週期解決的特定情況是 zval 已遞減但仍為非零值的情況。基本上,循環查看哪些值可以進一步遞減,然後釋放值為零的值。實際發生的情況是 PHP 跟踪所有根容器 (zval)。無論垃圾回收是否開啟,都會執行此操作(因為它只需執行此操作,而無需詢問垃圾回收是否開啟,等等)。此根緩衝區最多可容納 10,000 個根(固定大小,但這可以更改)。當它填滿時,垃圾回收機制將啟動,並開始分析此緩衝區。 GC 例程首先要做的是遍歷根緩衝區並將所有 zval 計數遞減 1。在執行此操作時,它會使用類似複選標記的小標記標記每個標記,以便它只遞減一次根。然後,它再次遍歷並標記(這次使用一個小波浪線)所有已減少計數為零的 zval。非零的值將遞增,以便它們恢復其原始值。最後,它將再次滾動,從緩衝區中清除非零 zval,並釋放具有零 refcount 的值的存儲。 PHP 中始終啟用垃圾回收,但您可以在 php.ini 文件中使用指令 zend.enable_gc 關閉它。或者,您可以通過調用 gc_enable() 和 gc_disable() 函數在腳本中執行此操作。如上所述,如果啟用垃圾回收,則當根已滿時運行,但您可以覆蓋此設置並在您認為合適的時候使用 gc_collect_cycles() 函數運行回收。並且,您可以使用 PHP 源代碼中 zend/zend_gc.c 中的 gc_root_buffer_max_entries 值修改根緩衝區的大小。總而言之,這允許您控制 GC 是否運行以及何時何地運行,這是一件好事,因為它有點資源密集型,因此可能不是您隨意運行的那種東西。

何時使用它

由於垃圾回收會影響性能,因此值得花點時間確定何時應使用它。首先,請記住,除非您公開運行它(使用gc_collect_cycles() 函數),否則正式垃圾回收不會在根表(10,000 個條目)填滿之前發生,並且由於此表位於作用域級別,因此對於小型函數來說不會發生這種情況。您應該在小型腳本上使用它嗎?這取決於您。很難說運行垃圾回收之類的操作是一件壞事,但如果您有小型、快速運行的腳本,這些腳本啟動然後結束並消失,那麼可能不會有太多回報。但是,如果您的服務器運行許多保持持久的小型腳本,那麼它可能值得付出努力。唯一真正知道的方法是為您的應用程序設置基準並查看。當然,如果您有長時間運行的腳本,尤其是永不結束的腳本,那麼如果您想防止我們上面討論的那種內存洩漏,則垃圾回收至關重要。也許最重要的是,我們應該始終嘗試遵循良好的編程指南,以便我們最大限度地減少或消除全局變量,並將我們的變量綁定到作用域,以便即使我們有長時間運行的腳本,我們也可以在函數結束時釋放該內存,而不是腳本結束時。還要注意何時在數組中使用數組或對象引用對象,因為這種情況會導致內存洩漏,並且是正式垃圾回收過程的真正目標。

圖片來自 Fotolia

PHP 垃圾回收常見問題解答 (FAQ)

(此處省略FAQ部分,因為篇幅過長,且與偽原創目標不符。FAQ部分內容與原文高度重合,偽原創難度大,且修改後可能改變原意。)

以上是PHP主|更好地了解PHP的垃圾收集的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
PHP的當前狀態:查看網絡開發趨勢PHP的當前狀態:查看網絡開發趨勢Apr 13, 2025 am 12:20 AM

PHP在現代Web開發中仍然重要,尤其在內容管理和電子商務平台。 1)PHP擁有豐富的生態系統和強大框架支持,如Laravel和Symfony。 2)性能優化可通過OPcache和Nginx實現。 3)PHP8.0引入JIT編譯器,提升性能。 4)雲原生應用通過Docker和Kubernetes部署,提高靈活性和可擴展性。

PHP與其他語言:比較PHP與其他語言:比較Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP與Python:核心功能PHP與Python:核心功能Apr 13, 2025 am 12:16 AM

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

PHP:網絡開發的關鍵語言PHP:網絡開發的關鍵語言Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP:許多網站的基礎PHP:許多網站的基礎Apr 13, 2025 am 12:07 AM

PHP成為許多網站首選技術棧的原因包括其易用性、強大社區支持和廣泛應用。 1)易於學習和使用,適合初學者。 2)擁有龐大的開發者社區,資源豐富。 3)廣泛應用於WordPress、Drupal等平台。 4)與Web服務器緊密集成,簡化開發部署。

超越炒作:評估當今PHP的角色超越炒作:評估當今PHP的角色Apr 12, 2025 am 12:17 AM

PHP在現代編程中仍然是一個強大且廣泛使用的工具,尤其在web開發領域。 1)PHP易用且與數據庫集成無縫,是許多開發者的首選。 2)它支持動態內容生成和麵向對象編程,適合快速創建和維護網站。 3)PHP的性能可以通過緩存和優化數據庫查詢來提升,其廣泛的社區和豐富生態系統使其在當今技術棧中仍具重要地位。

PHP中的弱參考是什麼?什麼時候有用?PHP中的弱參考是什麼?什麼時候有用?Apr 12, 2025 am 12:13 AM

在PHP中,弱引用是通過WeakReference類實現的,不會阻止垃圾回收器回收對象。弱引用適用於緩存系統和事件監聽器等場景,需注意其不能保證對象存活,且垃圾回收可能延遲。

解釋PHP中的__ Invoke Magic方法。解釋PHP中的__ Invoke Magic方法。Apr 12, 2025 am 12:07 AM

\_\_invoke方法允許對象像函數一樣被調用。 1.定義\_\_invoke方法使對象可被調用。 2.使用$obj(...)語法時,PHP會執行\_\_invoke方法。 3.適用於日誌記錄和計算器等場景,提高代碼靈活性和可讀性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。