在 Web 開發中,記憶體洩漏、單腳本佔用過高導致 PHP-FPM 進程頻繁重啟、OOM Killer 介入等問題屢見不鮮。PHP 提供的 memory_get_usage() 與 memory_get_peak_usage() 兩大內建函數,能以字節級精度回報腳本當前及峰值記憶體分配量,是效能調優、洩漏排查的利器。
| 函數 | 返回值 | 說明 |
|---|---|---|
memory_get_usage(bool $real_usage = false) | int (bytes) | 當前腳本已分配記憶體;$real_usage=true 返回系統實際分配量 (含分配器元數據),false 僅返回 emalloc() 統計值。 |
memory_get_peak_usage(bool $real_usage = false) | int (bytes) | 腳本啟動以來的記憶體分配峰值。 |
getrusage() | array | 返回 CPU 時間、頁面錯誤、上下文切換等系統資源用量 (僅 Linux/Unix 支援)。 |
<?php
echo '啟動記憶體:' . memory_get_usage() . \"\\n\"; // 147296
$tmp = str_repeat('hello', 1000); // 分配約 5KB 字串
echo '分配後記憶體:' . memory_get_usage() . \"\\n\"; // 152456 (+5160 bytes)
unset($tmp); // 釋放變量
echo '釋放後記憶體:' . memory_get_usage() . \"\\n\"; // 147296 回歸基線
?>
關鍵洞見:
unset() 能立即釋放變量佔用的 zval 結構體 及其引用的字串緩衝區,記憶體歸還給 PHP 分配器 (不一定歸還 OS)。unset(),可顯著降低峰值記憶體,避免觸發 memory_limit。mysqli_free_result()、fclose()、curl_close()。function memory_usage_readable(): string
{
if (!function_exists('memory_get_usage')) {
return 'N/A';
}
$mb = memory_get_usage(true) / 1024 / 1024;
return round($mb, 2) . ' MB';
}
// 使用示例
echo '當前記憶體:' . memory_usage_readable(); // 例如 2.34 MB
Generator 迭代器 vs 陣列載入,前者記憶體恆定,後者線性增長。memory_get_usage(),配合 memory_get_peak_usage() 找出持續增長的區塊。serialize() vs igbinary vs msgpack 序列化後字串大小,選擇最省記憶體的方案。microtime(true) 做時空綜合分析:記憶體-時間權衡曲線,找到最佳平衡點。opcache.enable_cli=0,避免緩存干擾基準測試。memory_get_usage(true) 獲取系統實際分配量,更貼近 memory_limit 判定邏輯。memory_get_usage() > memory_limit * 0.8 並主動重啟/回收。memory_get_usage() 只負責「快照」,不負責「定位」。掌握 memory_get_usage() 系列函數,讓記憶體優化不再靠猜,而是憑數據說話。下次遇到「Allowed memory size exhausted」,請先在關鍵路徑埋點,再對症下藥!