關於PHP記憶體洩漏的問題

程式設計愛好者發表於2021-01-21

通常情況下PHP是很少發生記憶體洩漏這種問題的,只有在PHP記憶體耗盡了才會導致記憶體洩漏的問題出現(一般這種情況下多數都是自己程式碼寫的有問題或者第三方請求導致的)。

檢視記憶體佔用一般有三個點需要注意:
  • RSS - Resident Set Size 實際佔用的實體記憶體(這個包含了共享記憶體的佔用空間)
  • USS - Unique Set Size 程式獨自佔用的實體記憶體(這個不包含共享記憶體佔用的空間)
  • PSS - Proportional Set Size 實際佔用的實體記憶體(按比例分配共享庫所佔用的記憶體)
一般在檢視某個程式時,可能是:
cat /proc/程式ID/status  | grep RSS

如果這樣查的話,所查的記憶體佔用可能是不準的,因為RSS所佔用的記憶體裡包含了共享記憶體在內(共享記憶體會重複計算多次),從而並不是所查程式真正的記憶體佔用值。

這個時候可以通過檢視USS或PSS,[推薦使用smem指令檢視] 能更加準確的查到程式實際所佔用的記憶體值是多少,如下:
關於PHP記憶體洩漏的問題

如果是想查某個程式的記憶體使用,例如PHP:
smem -M php | grep USS

清理記憶體碎片化:

有的時候,可能會遇到記憶體洩漏而定位不到的問題,通過工具(trace | swoole_tracker等)也可能無法定位到,但是通過smem檢視記憶體卻是一直在飆升,這很有可能就是遇到了PHP記憶體碎片化的問題了。
記憶體碎片化其實和PHP的記憶體分配演算法有關… 大概原理是:當所申請的記憶體空間小於3072個位元組時,PHP就會認定是一個小記憶體,然後PHP就會把所有的小記憶體給快取起來,
即使通過使用unset()這類函式對某個變數值進行釋放時,PHP也不會把釋放後的空間歸還於作業系統,以保證內管理的效率。

如何解決記憶體碎片化問題呢?PHP提供了一個函式:

gc_mem_caches()

可以呼叫這個函式,手動清除記憶體碎片化的問題。
除了用gc_mem_caches()函式外,還可以通過擴充套件的方式來替換PHP的記憶體管理模組(比如使用jemalloc)。但是目前和記憶體相關的演算法可能都存在記憶體碎片化的問題。


最後:

在PHP-FPM模式下,記憶體洩漏一般是很少遇到的,如果真遇到了, 也可能是自己寫的程式碼或者呼叫了第三方的什麼元件導致的問題。

  • 首先定位問題:記憶體洩漏的原因所在。也可以在php-fpm的配置檔案裡,開啟php的log記錄,通過log定位問題。
  • 解決問題:根據具體的問題所在進行解決
  • 最後如果遇到了記憶體碎片話問題,可以嘗試用gc_mem_caches()函式,手動清除掉。

希望幫助了自己也幫到了你^_^ 有哪裡不正確的,還請多多指教。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章