若錯誤提示為“Allowed memory size exhausted”(如Fatal error: Allowed memory size of X bytes exhausted
),可通過增加PHP內存限制快速緩解問題。
/etc/php/{版本}/apache2/php.ini
(Apache)或/etc/php/{版本}/fpm/php.ini
(Nginx+PHP-FPM)。搜索memory_limit
參數,將其值從默認的128M
或256M
調整為更高的數值(如512M
或1G
),保存后重啟Web服務:sudo systemctl restart apache2 # Apache
sudo systemctl restart php{版本}-fpm # PHP-FPM(如php8.1-fpm)
public/index.php
)頂部添加:ini_set('memory_limit', '512M');
注意:增加內存限制僅為臨時解決方案,需結合后續優化避免依賴。
使用工具定位內存泄漏的具體代碼位置,避免盲目優化:
memory_get_usage()
和memory_get_peak_usage()
,輸出當前內存使用量及峰值,對比不同階段的內存變化,判斷是否持續增長:echo '當前內存使用:'.memory_get_usage()/1024/1024.'MB<br>';
echo '內存峰值:'.memory_get_peak_usage()/1024/1024.'MB<br>';
cachegrind
文件),查看函數調用棧及內存占用情況,定位高內存消耗的函數或方法。根據檢測結果,針對性修復常見的內存泄漏場景:
ObjectA
持有ObjectB
的實例,ObjectB
又持有ObjectA
的實例),可使用WeakReference
(弱引用)打破循環,或重構代碼將對象存儲在數組中而非相互引用。unset()
清除不再需要的大對象、數組或數據庫結果集(如$result->close()
關閉數據庫游標);對于MySQL查詢,確保使用mysqli_free_result()
釋放結果集內存。LIMIT offset, size
)或yield
生成器逐行處理,避免一次性加載所有數據到內存:// 使用yield逐行讀取
public function getLargeData()
{
$query = Db::table('large_table')->field('id, name')->select();
foreach ($query as $row) {
yield $row;
}
}
config/cache.php
)中開啟查詢緩存,減少重復查詢的內存消耗:'query_cache' => [
'type' => 'redis', // 使用Redis作為緩存驅動
'expire' => 3600, // 緩存有效期(秒)
],
with
方法預加載關聯數據(如User::with('orders')->select()
),減少數據庫查詢次數及內存占用。gc_enable()
手動觸發垃圾回收(如在腳本關鍵節點調用),及時回收無引用的對象。通過以上步驟,可逐步定位并解決ThinkPHP在Ubuntu環境下的內存泄漏問題,提升應用的穩定性和性能。