您好,登錄后才能下訂單哦!
原文地址:https://www.airpair.com/php/fatal-error-allowed-memory-size
內存不足錯誤是PHP開發人員遇到的最常見和難以解決的問題之一 - 特別是對于處理大量數據的應用程序 - 這要歸功于PHP相對保守的默認內存設置。事實上,僅Stack Overflow上有超過1,300個與PHP內存錯誤相關的問題。
98%的時間此錯誤來自加載到內存中的內容比您在一個進程中設置PHP要處理的內容多。還有其他原因,但這些不太常見 - 如果您使用的是PHP 5.3及更高版本,則很少會出現內存泄漏。
如果您不確定您的PHP內存限制設置為什么,它將有助于包含在錯誤消息中。但是,大小以字節為單位報告,因此我們為您完成了一些轉換:
您的第一個行動是增加內存限制。注意,這是一個臨時調試生產。目標是將內存增加到我們讓應用程序再次工作以減少內存使用量的程度。一旦減少了內存使用量,就可以將內存限制降低到更合適的值。您的計劃應該是使用盡可能少的內存,因為應用程序可以在生產服務器中根據用戶(人或程序)的工作負載正常運行。我通常建議將內存限制設置為高,例如1GB,假設你在RAM中至少有150%的空閑內存。
此外,永遠不要在生產服務器上進行這些測試,除非您確定您有足夠的RAM 并且您完全理解Web服務器進程如何消耗內存。如果有許多并發進程在運行,每個進程都使用大量內存,您可以輕松地使服務器陷入困境。我絕不會建議-1在生產環境中將內存限制設置為(無限制)。那是一場災難。不要犯那個新手的錯誤。
那你怎么做的?簡單 - 在進程耗盡內存之前,在代碼的早期以編程方式增加內存限制。如果以這種方式執行,只有在調用該段代碼時才能為PHP提供額外的內存,而不是增加所有 PHP進程的內存限制。
<?php
ini_set('memory_limit', '1024M'); // or you could use 1G
打電話給急診室,因為你可能會在那里結束。不,說真的,這里有幾件你可以做的事情。
首先,你需要問問自己什么時候開始發生。以前是否有效,現在不是嗎?如果是這樣,請考慮可能發生的變化。隔離問題。
在問題出現之前,您可能沒有觸摸過代碼。那么,還有什么可以改變的呢?有外部依賴嗎?也許是數據庫或用戶導入的文件?把它放在你的嫌疑人名單上并開始調查。
從小開始; 從你“思考”問題開始,并試圖證明自己是錯的。如果你不能,繼續前往下一個嫌犯。看看你的代碼在它過早退出之前進入了多遠,然后從那里開始處理調用堆棧(var_dump debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)如果你沒有安裝Xdebug)。如果您可以使用Xdebug或Zend Debugger進行交互式調試,請執行此操作并在問題區域之前放置斷點。
我曾經遇到過導入后Excel文件內存不足的問題。幾個月來它工作正常,但突然停了下來。我覺得我花了至少5小時的不懈調試之前,我發現了問題:在某種程度上被插入隨機數據,一個工作表的單元用戶的。顯然PHP只是亂了,我仍然沒有發現根本原因,盡管知道觸發器。
通過問自己改變了什么,我可以節省很多時間。答案非常明顯 - 用戶和數據庫輸入的數據。你可以有類似的經歷。
在任何情況下,都可以依靠一個工具來幫助診斷您正在使用的內存量以及代碼中使用大量內存的位置:Xdebug。您可以使用軟件包管理器如安裝yum,apt-get,port,和homebrew; 安裝預先構建的二進制文件; 使用pecl; 或者只是自己編譯。
安裝Xdebug之后,您只需刷新頁面,或者如果您的代碼要在shell中運行,請在CLI中重新運行它。PHP現在將拋出更多信息性錯誤,包括一個調用堆棧,它將通過文件路徑,行號甚至最后調用的函數準確地告訴您腳本停止的位置。
如果您需要更詳細的信息,您需要生成所謂的“跟蹤文件”。為此,請將xdebug.auto_traceand和xdebug.show_mem_deltaconfig指令設置為1。跟蹤文件通常保存在/tmp或中/var/tmp,但您可以通過查看xdebug.trace_output_dir指令來檢查輸出路徑phpinfo()。
只需運行代碼,即使早期內存不足,也會創建跟蹤文件(包括內存使用情況)。
要找到問題,請從跟蹤文件的底部開始,然后逐步完成。查找具有大數字的增量(帶有+或 - 的數字),并記住它們以字節顯示。1024字節= 1千字節。
完成調試后,請務必xdebug.auto_trace回到0。跟蹤文件可能變得非常大,非常快,并占用磁盤空間。
這是一個關于PHP如何在內部處理內存的精彩幻燈片。
使用以下腳本并嘗試查明問題所在。更好的是,安裝Xdebug并生成跟蹤文件。
<?php
function get_usage_in_kb(){
echo memory_get_usage()/1024.0 . " kb \n";
}
class Profiler
{
protected $startTime = 0;
public function timerStart(){
$this->startTime = microtime(true);
}
function timerEnd(){
echo number_format( (microtime(true) - $this->startTime)*1000, 2 ), ' ms';
}
}
class ProfilerHolder {
protected $profiler;
public function __construct( Profiler $profiler ){
$this->profiler = $profiler;
}
}
ini_set('memory_limit', '1M');
$profiler = new Profiler();
$profiler->timerStart();
get_usage_in_kb();
$holder = new ProfilerHolder( $profiler );
$b = null;
/**
* @return string
*/
function make_dummy_data()
{
return str_repeat( "Hello|", 114242 );
}
考慮到所有這些提示,您應該能夠修復任何內存耗盡錯誤。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。