PHP 垃圾回收高級特性

PHP 垃圾回收高級特性

1. 循環引用與內存泄漏

單純的引用計數在遇到循環引用時會導致內存泄漏,主要原因是引用計數無法正確識別那些僅通過循環引用相互關聯但實際上已經不可達的對象。

1.1 引用計數的基本原理

引用計數是一種內存管理機制,通過維護每個對象的引用計數來決定對象是否可以被銷毀:

  • 創建對象:引用計數初始為 1
  • 新增引用:引用計數增加
  • 刪除引用:引用計數減少
  • 銷毀對象:當引用計數變為 0 時,對象被銷毀,其內存被回收

2. 循環引用詳解

2.1 循環引用的定義

循環引用是指兩個或多個對象相互引用,形成一個閉環。例如:

$a = new UsersEntity();
$b = new UsersEntity();
$a->ref = $b; // $a 引用了 $b
$b->ref = $a; // $b 引用了 $a

在這個例子中:

  • $a 的引用計數為 1(被 $b->ref 引用)
  • $b 的引用計數為 1(被 $a->ref 引用)

注意:即使腳本中不再使用 $a 和 $b,它們的引用計數都不會變為 0,因為它們相互引用。

2.2 引用計數的局限性

引用計數無法判斷循環引用對象是否真正被程序所需。即使這些對象在邏輯上不可達(沒有外部引用指向它們),它們之間的引用關系仍然會導致引用計數始終大于 0。


3. 內存泄漏示例

3.1 基本示例

gc_enable(); // 啟用垃圾回收
$a = new UsersEntity();
$b = new UsersEntity();
$a->ref = $b; // 循環引用
$b->ref = $a;unset($a);
unset($b);

重要:即使沒有手動觸發垃圾回收,這里也會出現內存泄漏。即使 $a 和 $b 已經被 unset,它們仍然在相互引用,引用計數器無法減少到 0。

3.2 實際應用示例

public function getStatusWithCycle()
{gc_enable(); // 啟用垃圾回收$a = new UsersEntity();$b = new UsersEntity();$a->ref = $b; // 循環引用$b->ref = $a;unset($a);unset($b);$endStatus = gc_status();return ['end_status' => $endStatus];
}

返回結果示例:

{"data": {"end_status": {"runs": 0,"collected": 0,"threshold": 10001,"roots": 2433}}
}

4. 垃圾回收器的解決方案

為了彌補引用計數的局限性,PHP 引入了垃圾回收器(GC),采用了基于根集合(roots)和可達性分析的算法:

  1. 根集合:程序中所有可以直接訪問的對象
  2. 標記階段:遍歷根集合,標記所有可達的對象
  3. 清除階段:回收未被標記的對象,包括循環引用的對象
gc_collect_cycles(); // 手動觸發垃圾回收

5. 自動垃圾回收機制

如果啟用了垃圾回收機制,即使沒有手動調用 gc_collect_cycles(),理論上內存溢出的風險大大降低,但仍然可能發生,取決于以下因素:

5.1 自動垃圾回收觸發條件

  • PHP 的垃圾回收器在運行時會自動檢測是否需要回收循環引用的內存資源
  • 垃圾回收的觸發基于根集合的增長(roots)和預定義的閾值(gc_status()['threshold']
  • 如果 roots 增長未達到 threshold,垃圾回收不會觸發

注意:如果代碼中循環引用對象的生成速度超過垃圾回收器的觸發速度,可能出現短期內的內存占用高峰甚至溢出。

5.2 腳本運行時長和負載

短生命周期腳本
  • 大多數 PHP 網頁腳本屬于此類
  • 腳本結束時會清理所有內存,包括循環引用的對象
  • 通常不會內存溢出,但可能出現瞬間內存使用過高
長生命周期腳本
  • 守護進程、隊列處理器、WebSocket 服務等
  • 可能持續運行并產生大量循環引用對象
  • 如果垃圾回收未及時觸發,內存使用會逐漸增加

6. 內存管理最佳實踐

6.1 如何降低內存溢出風險

  1. 配置優化

    • 確保 memory_limit 配置足夠高
    • 適當調整垃圾回收閾值
  2. 代碼優化

    • 避免頻繁創建循環引用對象
    • 及時打破不必要的引用關系
  3. 主動管理

    • 使用 unset() 及時打破引用關系
    • 在適當位置手動觸發垃圾回收

6.2 監控和優化建議

  1. 內存監控

    • 定期檢查 gc_status() 的 roots 和 collected 值
    • 引入內存監控和日志機制
  2. 性能優化

    • 優化代碼結構
    • 減少不必要的對象創建
    • 適當調用 gc_collect_cycles()

總結

關鍵要點

  • 循環引用是引用計數機制的主要缺陷
  • PHP 的垃圾回收器通過可達性分析解決循環引用問題
  • 合理使用手動垃圾回收和內存監控可有效預防內存溢出
  • 在高負載場景下需要特別注意內存管理

通過優化代碼結構和適當調用 gc_collect_cycles(),可以有效避免內存溢出問題。在實際應用中,應結合具體場景選擇合適的內存管理策略。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83002.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83002.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83002.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

奈雪小程序任務腳本

功能概述 該腳本用于自動完成奈雪點單小程序的每日任務,包括: 自動檢測 Token 有效性自動簽到(如果未簽到)獲取用戶基礎信息(昵稱、手機號)查詢當前奈雪幣余額記錄連續簽到天數支持多賬號執行&#xff0c…

基于cornerstone3D的dicom影像瀏覽器 第二十七章 設置vr相機,復位視圖

文章目錄 前言一、VR視圖設置相機位置1. 相機位置參數2. 修改mprvr.js3. 調用流程1) 修改Toolbar3D.vue2) 修改View3d.vue3) 修改DisplayerArea3D.vue 二、所有視圖復位1.復位流程說明2. 調用流程1) Toolbar3D中添加"復位"按鈕,發送reset事件2) View3d.vu…

Opencv4 c++ 自用筆記 03 滑動條、相機與視頻操作

1. 相機與視頻操作 1.1 打開視頻/相機 OpenCV 中 imread() 只能讀取靜態圖像,若要讀取視頻文件或攝像頭流,需要使用 VideoCapture 類: // 構造函數 cv::VideoCapture::VideoCapture(); cv::VideoCapture…

身份證發給別人怎么加水印?賽文奧特曼身份證添加水印教程

我們經常需要使用身份證照片進行身份驗證、資料提交等操作。然而,直接將身份證照片發送給他人或上傳到網絡存在一定的信息泄露風險。為了更好地保護個人隱私,我們可以使用 簡鹿水印助手 這款工具,在身份證照片上添加專屬水印,從而…

十、【核心功能篇】項目與模塊管理:前端頁面開發與后端 API 聯調實戰

【核心功能篇】項目與模塊管理:前端頁面開發與后端 API 聯調實戰 前言準備工作第一部分:完善項目管理功能 (Project)1. 創建/編輯項目的表單對話框組件 第二部分:模塊管理功能 (集成到項目詳情頁)1. 創建模塊相關的 API 服務 (src/api/module…

ES分詞搜索

ES的使用 前言作者使用的版本作者需求 簡介ES簡略介紹ik分詞器簡介 使用es的直接簡單使用es的查詢 es在java中使用備注說明 前言 作者使用的版本 es: 7.17.27spring-boot-starter-data-elasticsearch: 7.14.2 作者需求 作者接到一個業務需求,我們系統有份數據被…

Axure設計案例——科技感立體柱狀圖

想讓你的數據展示告別平淡無奇,成為吸引全場目光的焦點嗎?快來瞧瞧這個Axure設計的科技感立體柱狀圖案例!科技感設計風格借助逼真的立體效果打破傳統柱狀圖的平面感,營造出一種令人眼前一亮的視覺震撼。每一個柱狀體都仿佛是真實存…

惡意npm與VS Code包竊取數據及加密貨幣資產

60個npm包竊取系統敏感信息 安全研究人員在npm軟件包注冊表中發現60個惡意組件,這些組件能夠收集主機名、IP地址、DNS服務器和用戶目錄信息,并將其發送至Discord平臺控制的終端節點。據Socket安全研究員Kirill Boychenko上周發布的報告顯示,…

leetcode 2359. 找到離給定兩個節點最近的節點

給你一個 n 個節點的 有向圖 ,節點編號為 0 到 n - 1 ,每個節點 至多 有一條出邊。 有向圖用大小為 n 下標從 0 開始的數組 edges 表示,表示節點 i 有一條有向邊指向 edges[i] 。如果節點 i 沒有出邊,那么 edges[i] -1 。 同時…

1. pytorch手寫數字預測

1. pytorch手寫數字預測 1.背景2.準備數據集2.定義模型3.dataloader和訓練4.訓練模型5.測試模型6.保存模型 1.背景 因為自身的研究方向是多模態目標跟蹤,突然對其他的視覺方向產生了興趣,所以心血來潮的回到最經典的視覺任務手寫數字預測上來&#xff0…

AWS WebRTC:獲取ICE服務地址(part 2): ICE Agent的作用

上一篇,已經獲取到了ICE服務地址,從返回結果中看,是兩組TURN服務地址。 拿到這些地址有什么用呢?接下來就要說到WebRTC中ICE Agent的作用了,返回的服務地址會傳給WebRTC最終給到ICE Agent。 ICE Agent的作用&#xf…

大數據時代的利劍:Bright Data網頁抓取與自動化工具共建高效數據采集新生態

目錄 一、為何要選用Bright Data網頁自動化抓取——幫助我們高效高質解決以下問題! 二、Bright Data網頁抓取工具 - 網頁爬蟲工具實測 2.1 首先注冊用戶 2.2 首先點擊 Proxies & Scraping ,再點擊瀏覽器API的開始使用 2.3 填寫通道名稱&#xff…

指紋識別+精準化POC攻擊

開發目的 解決漏洞掃描器的痛點 第一就是掃描量太大,對一個站點掃描了大量的無用 POC,浪費時間 指紋識別后還需要根據對應的指紋去進行 payload 掃描,非常的麻煩 開發思路 我們的思路分為大體分為指紋POC掃描 所以思路大概從這幾個方面…

【Day40】

DAY 40 訓練和測試的規范寫法 知識點回顧: 彩色和灰度圖片測試和訓練的規范寫法:封裝在函數中展平操作:除第一個維度batchsize外全部展平dropout操作:訓練階段隨機丟棄神經元,測試階段eval模式關閉dropout 作業&#x…

【HTML-13】HTML表格合并技術詳解:打造專業數據展示

表格是HTML中展示結構化數據的重要元素,而表格合并則是提升表格表現力的關鍵技術。本文將全面介紹HTML中的表格合并方法,幫助您創建更專業、更靈活的數據展示界面。 1. 表格合并基礎概念 在HTML中,表格合并主要通過兩個屬性實現&#xff1a…

<uniapp><threejs>在uniapp中,怎么使用threejs來顯示3D圖形?

前言 本專欄是基于uniapp實現手機端各種小功能的程序,并且基于各種通訊協議如http、websocekt等,實現手機端作為客戶端(或者是手持機、PDA等),與服務端進行數據通訊的實例開發。 發文平臺 CSDN 環境配置 系統:windows 平臺:visual studio code、HBuilderX(uniapp開…

如何制作全景VR圖?

全景VR圖,特別是720度全景VR,為觀眾提供一種沉浸式體驗。 全景VR圖能夠捕捉場景的全貌,還能將多個角度的圖片或視頻無縫拼接成一個完整的全景視角,讓觀眾在虛擬環境中自由探索。隨著虛擬現實(VR)技術的飛速…

前端使用qrcode來生成二維碼的時候中間添加logo圖標

這個開源倉庫可以讓你在前端頁面中生成二維碼圖片,并且支持調整前景色和背景色,但是有個問題,就是不能添加logo圖片。issue: GitHub Where software is built 但是已經有解決方案了: add a logo picture Issue #21…

【C語言】函數指針及其應用

目錄 1.1 函數指針的概念和應用 1.2 賦值與內存模型 1.3 調用方式與注意事項 二、函數指針的使用 2.1 函數指針的定義和訪問 2.2 動態調度:用戶輸入驅動函數執行 2.3 函數指針數組進階應用 2.4 函數作為參數的高階抽象 三、回調函數 3.1 指針函數…

安裝flash-attention失敗的終極解決方案(WINDOWS環境)

想要看linux版本下安裝問題的請走這里:安裝flash-attention失敗的終極解決方案(LINUX環境) 其實,現在的flash-attention不像 v2.3.2之前的版本,基本上不兼容WINDOWS環境。但是在WINDOWS環境安裝總還是有那么一點不順暢…