情況一、程式操作資料過大
情境還原:一次讀取超過php可用記憶體上限的資料導致記憶體耗盡
<?php ini_set('memory_limit', '128M'); $string = str_pad('1', 128 * 1024 * 1024);
解決方法:
1、能用錢解決的問題都不是問題,如果程式要讀大檔案的機會不是很多,上限可預期,那麼透過ini_set('memory_limit', '1G'); 來設定一個更大的值或memory_limit=-1。內存管夠的話讓程式一直跑也可以。
2、如果程式需要考慮在小型記憶體機器上也能正常使用,那就需要優化程式了。如下,程式碼複雜了很多。
<?php //php7 以下版本通过 composer 引入 paragonie/random_compat ,为了方便来生成一个随机名称的临时文件 require "vendor/autoload.php"; ini_set('memory_limit', '128M'); //生成临时文件存放大字符串 $fileName = 'tmp'.bin2hex(random_bytes(5)).'.txt'; touch($fileName); for ( $i = 0; $i < 128; $i++ ) { $string = str_pad('1', 1 * 1024 * 1024); file_put_contents($fileName, $string, FILE_APPEND); } $handle = fopen($fileName, "r"); for ( $i = 0; $i <= filesize($fileName) / 1 * 1024 * 1024; $i++ ) { //do something $string = fread($handle, 1 * 1024 * 1024); } fclose($handle); unlink($fileName);
情況二、程式操作大數據時產生拷貝
情境還原:執行過程中對大變量進行了複製,導致記憶體不夠用。
<?php ini_set("memory_limit",'1M'); $string = str_pad('1', 1* 750 *1024); $string2 = $string; $string2 .= '1';
解決方法:
及早釋放無用變量,或以引用的形式操作原始資料。
<?php ini_set("memory_limit",'1M'); $string = str_pad('1', 1* 750 *1024); $string2 = $string; unset($string); $string2 .= '1';
情況三、配置不合理系統資源耗盡
#情境還原:因配置不合理導致記憶體不夠用,2G 記憶體機器上設定最大可以啟動100 個php-fpm 子進程,但實際啟動了50 個php-fpm 子進程後無法再啟動更多進程。
解決方法:
合理地設定 post_max_size、max_file_uploads、upload_max_filesize、max_input_vars、max_input_nesting_level 等參數並調優 php-fpm 相關參數。
情況四、無用的資料未及時釋放
情境還原:這種問題從程式邏輯上不是問題,但是無用的資料大量佔用記憶體導致資源不夠用,應該有針對性的做程式碼最佳化。
Laravel開發中用於監聽資料庫操作時有如下程式碼:
DB::listen(function ($query) { // query−>sql//query−>sql//query->bindings // $query->time });
#解決方法:
以上是php什麼情況記憶體洩露的詳細內容。更多資訊請關注PHP中文網其他相關文章!