簡體   English   中英

如何找到哪個PHP腳本泄漏內存?

[英]How to find which PHP script is leaking memory?

我的專用服務器有32GB內存,內存不斷上升,我現在必須每天重新啟動它。 這給我的客戶和金錢帶來了損失。

我很難找到內存泄漏的位置。 我在網上找到的只是人們說“使用xdebug”,但我找不到任何關於查找內存泄漏的xdebug教程。 我已經嘗試在函數調用之前和之后打印memory_get_usage但這是正確的方法嗎?

我有很多PHP腳本運行 - 一些來自訪問者,另一些來自cron作業 - 我需要找到哪一個正在泄漏內存並盡快修復它但我甚至不知道如何確定給定的功能是否是泄漏記憶與否。

我已經嘗試在函數調用之前和之后打印memory_get_usage,然后它會上升,但是如果我不止一次調用該函數,它就不再上升了。 有人可以解釋一下,並告訴我如何簡單輕松地判斷PHP函數是否有內存泄漏?

你可以做各種各樣的事情,但首先你應該盡量避免創建內存泄漏。

讓我澄清一下:PHP是一種腳本語言,它不是為長時間運行的腳本而設計的,因此它的內存管理並不是市場上最好的。 但為什么會這樣呢? 它的目的是在請求級別上調用,因此其運行范圍非常小(不超過2-3秒)。 其他一切都應該放在后台。

我可以做些什么來防止內存泄漏?

  1. 如果您的版本低於5.4,則需要處理循環引用,因為這些不是垃圾回收。

  2. 如果您需要連續運行腳本,您可能會考慮采用不同的方法。 嘗試一段while(true)實現,但在supervisor周圍包裝supervisorhttp://supervisord.org ),並在結束后調用它。 這樣你100%確定你永遠不會得到內存泄漏。

  3. 您可以使用xdebug分析腳本,並找出消耗大量內存的地方。

  4. 如果該類不再需要,您可以實現析構函數來取消設置所有引用。

     public function __destruct(){ $this->cleanup(); } public function cleanup() { //cleanup everything from attributes foreach (get_class_vars(__CLASS__) as $clsVar => $_) { unset($this->$clsVar); } //cleanup all objects inside data array if (is_array($this->_data)) { foreach ($this->_data as $value) { if (is_object($value) && method_exists($value, 'cleanUp')) { $value->cleanUp(); } } } } 
  5. 閱讀有關垃圾收集的PHP文檔http://us3.php.net/manual/en/features.gc.php

  6. 避免使用全局變量,因為這些變量從不被垃圾收集,需要顯式unset 如果你使用ZF或Symfony之類的框架可能是不可能的,那么如果你這樣做會破壞功能。

最后但並非最不重要的是,我想再次強調 ,PHP不適合長時間運行的腳本! 如果你有事情要做,那就需要連續運行你不應該因為PHP中的內存泄漏而崩潰,而是花時間學習更復雜的語言,比如JAVA或C#。

看看這個php擴展: https//github.com/arnaud-lb/php-memory-profiler 您可以轉儲不同格式的信息,並通過一些工具進行簡單分析,例如: Google Performance ToolsKCacheGrindQCacheGrind

我找到了適合我的方法:

  1. 安裝“ php-memprof ”擴展。 在你可以Ubuntu運行:

    sudo pecl install memprof

  2. 安裝“ google-perftools ”。 再次為Ubuntu:

    sudo apt-get install google-perftools

  3. 添加此代碼以開始您的腳本:

     if (function_exists('memprof_enable')) { memprof_enable(); } 
  4. 這個令人感到困惑的地方是你找到內存泄漏:

     if (function_exists("memprof_dump_pprof")) { $time = microtime(true); $f = fopen("/tmp/profile_$time.heap", "w"); memprof_dump_pprof($f); fclose($f); echo "Memory profile dumped. "; } 

    在我的情況下,每100次運行就在大循環內。

  5. 運行google-pprof比較2個內存轉儲:

     google-pprof --web --base=/tmp/profile_17.heap /tmp/profile_18.heap 

    這將在您的瀏覽器中打開這樣的svg圖像:

    來自doc的樣本

    您可以在gperftools文檔中找到數字和名稱的描述

PS修復漏洞在php級別不能保證解釋器中沒有內存泄漏。 在我的情況下,我最終只是在較長時間內重新啟動sctipt。

我不是內存使用方面的專家,但也許這種方法可以幫助您檢測有問題的腳本:

獲取信息:1。使用apache訪問日志文件2.創建自己的內存使用日志文件( http://www.webhostingtalk.com/showthread.php?t=617742

檢查內存使用率上升的時間並與apache訪問日志進行比較。

它至少會向您提供有關使用率是緩慢且持續增長還是從某個特定點開始使用的信息。

祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM