PHP記憶體洩漏問題解析

2021-10-24 06:30:56 字數 1828 閱讀 1696

記憶體洩漏指的是在程式執行過程中申請了記憶體,但是在使用完成後沒有及時釋放的現象, 對於普通執行時間較短的程式來說可能問題不會那麼明顯,但是對於長時間執行的程式, 比如web伺服器,後台程序等就比較明顯了,隨著系統執行占用的記憶體會持續上公升, 可能會因為占用記憶體過高而崩潰,或被系統殺掉

php屬於高階語言,語言級別並沒有記憶體的概念,在使用過程中完全不需要主動申請或釋放記憶體, 所以在php使用者**級別也就不存在記憶體洩漏的概念了。

但畢竟php是使用c編寫的直譯器,而c語言的程式是可能出現記憶體洩漏問題,所以本質上還是一樣的,那麼可以這麼說:如果你的php程式記憶體洩漏了,會有三種可能:

首先肯能是自己的**有問題,比如沒有及時釋放大記憶體的變數等。

很多公司都會有自己的php擴充套件,而擴充套件通常也使用c/c++來編寫,這樣擴充套件本身也可能會因為記憶體不正確釋放而導致記憶體洩漏。

有些擴充套件是對第三方庫的一種包裹, 比如php的sqlite資料庫操作介面主要是在libsqlite之上進行了封裝,所以如果 libsqlite本身有記憶體洩漏的話,那也可能會帶來問題。

根據官方的介紹,php-cgi不存在記憶體洩漏,每個請求完成後php-cgi會**記憶體,但是不會釋放給作業系統,這樣就會導致大量記憶體被php-cgi占用。(這個對於記憶體不大的伺服器,比如雲主機就太致命了,利用命令:ps aux|grep php-cgi|grep -v grep|awk ''可以查詢佔比1%的php-cgi的pid,然後kill掉(kill -9),這個方法比較好) 

官方的解決辦法是降低php_fcgi_max_requests的值。

這裡先簡單說一下nginx+php-fpm模式的工作原理:

nginx伺服器fork出n個子程序(worker),php-fpm管理器fork出n個子程序。

當有使用者請求,nginx的乙個worker接收請求,並將請求拋到socket中。

php-fpm空閒的子程序監聽到socket中有請求,接收並處理請求。

這裡要重點說一下第三步驟。第三步涉及到php-fpm程序生命週期的東西。乙個php-fpm的生命週期大致是這樣的:模組初始化(minit)-> 模組啟用(rinit)-> 請求處理 -> 模組停用(rshutdown) -> 模組啟用(rinit)-> 請求處理 -> 模組停用(rshutdown)……. 模組啟用(rinit)-> 請求處理 -> 模組停用(rshutdown)-> 模組關閉(mshutdown)。在乙個php-fpm程序的生命週期裡,會有多次的模組啟用(rinit)-> 請求處理 -> 模組停用(rshutdown)的過程。這個「請求處理」的大致過程是這樣的:php讀取相應的php檔案,對其進行詞法分析,生成opcode,zend虛擬機器執行opcode。

php配置檔案裡面的memory_limit 這個東西,其實,它限制的只是這個「請求處理」的記憶體。所以,這個引數跟php-fpm程序占用的記憶體並沒有什麼關係。php是用c寫的,所以,難免又會一些記憶體洩露。也就是說,在「請求處理」這個過程結束後,有些變數沒有被銷毀,然後就導致乙個php-fpm程序占用的記憶體越來越大。

那麼,有什麼辦法能阻止這個問題呢? 

php-fpm.conf中有個引數pm.max_requests,等同於php_fcgi_max_requests。該值的意思是乙個fpm程序處理多少個請求後自動殺掉另起新程序。 

這個引數預設是關閉的,我們需要開啟這個引數,並且適當降低這個值,用以讓php-fpm自動的釋放記憶體。另乙個跟它有關聯的值max_children,這個是每次php-fpm會建立多少個程序,這樣實際上的記憶體消耗是max_children*max_requests*每個請求使用記憶體,根據這個我們可以預估一下記憶體的使用情況,就不用再寫指令碼去kill了。

PHP記憶體洩漏

如果php物件存在遞迴引用,就會出現記憶體洩漏。這個bug在php裡已經存在很久很久了,先讓我們來重現這個bug,如下 class foo class bar for i 0 i 100 i 執行以上 你會發現,記憶體使用量本應該不變才對,可實際上卻是不斷增加,unset沒有完全生效。現在的開發很多...

記憶體洩漏問題

這個函式動態地分配乙個整數,但從未使用刪除釋放它。因為指標和普通變數遵循相同的規則,函式結束時,pnvalue會超出範圍。因為pnvalue是唯一的變數的位址動態分配的整數,pnvalue摧毀時不再有動態分配的記憶體引用。這就是所謂的記憶體洩漏。因此,動態分配的整數不能被刪除,從而不能重新分配或重用...

php記憶體洩漏 記憶體限制memory limit

記憶體洩漏指的是在程式執行過程中申請了記憶體,但是在使用完成後沒有及時釋放的現象,對於普通執行時間較短的程式來說可能問題不會那麼明顯,但是對於長時間執行的程式,比如web伺服器,後台程序等就比較明顯了,隨著系統執行占用的記憶體會持續上公升,可能會因為占用記憶體過高而崩潰,或被系統殺掉。這裡先簡單說一...