2017年1月22日 星期日

[PHP]關於記憶體使用的三兩事

通常在執行一些排程, 或是資料處理量較大的程式的時候常常會遇到

Fatal error: Allowed memory size of xxx bytes


這樣的錯誤, 通常一般人會想說, 那就調高就好了,

但這不會是很好的做法, 畢竟沒搞清楚為何會超過設定值.

以下為記憶體相關 function  ,
// 當前記憶體使用量
memory_get_usage();

// 此次執行記憶體峰值
memory_get_peak_usage();

// 單位轉換
function convert($size){
$unit=array('b','kb','mb','gb','tb','pb');
return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
}

切記!通常使用過量都是因峰值造成,故debug請用
// 此次執行記憶體峰值
memory_get_peak_usage();

另外,最近在使用Laravel Collect function 有稍微注意了一下內部核心寫法有使用到 array_map()

發現使用 array_map 與 使用單純 foreach + & 的方式 記憶體峰值大約差了三倍...


所以如果有使用較大量資料時可能要考量一下...

 

最後來分享一下較常發生記憶體使用過量的原因&解法,

  1. 預設值太小(這部分須自行評估, 特別注意這次一次的使用量, 如果設定太大可能會造成其他服務癱瘓)
    ini_set("memory_limit","256M");


  2. 迴圈設assign參數造成占用過多記憶體
    // 善用&, 可以減少記憶體浪費
    foreach (range(1, 40) as $key => &$value)
    {
    $value = $value * $value;
    }
    // 又或者要記得清除不會在被使用的參數
    unset($value);


  3. 瞬間記憶體峰值過高(json_decode較大資料時容易發生)
    // 這個要看情況,之前遇到我是提出分批decode的方式。
    // 不然就要尋求第三方套件了,但之前試過大概也是使用了80%