PHP錯誤:Allowed memory size of xxx bytes(二)

在上一篇文章中,針對查詢數據表時候,php出現 「Allowed memory size of xxx bytes」的錯誤,在不修改php.ini配置的時候,用另外的函數來解決了這個問題,以犧牲部分性能的代價來換取內存空間,在這篇文章中,會說一下在讀取文件的時候出現這個問題的解決思路。
php

在讀取文件的時候,file_get_contents()和file()是你們慣用的兩個函數,由於操做會比較少一點,我這個地方下載了一個200M的日誌文件做爲操做對象。函數

// 這裏是通常的寫法
//$file = file_get_contents($log_file);
$file = file($log_file);
$start = memory_get_usage();
$end = memory_get_usage();
$used = $end - $start;
echo $used;

不管file_get_contents仍是file,都和預料中同樣,出現了錯誤」Fatal error: Allowed memory size of 134217728 bytes exhausted」。性能

如今咱們開始看另外幾種寫法測試

代碼1:日誌

這是採用fgets()每次讀取一行的結果,可是若是一行比較大的狀況下,也會出現內存不夠用的錯誤提示code

function test1($log_file) {
//    內存:664byte
//    時間:13.063009977341秒
    $fp = fopen($log_file, 'r+');
    while(! feof($fp)) {
        $row = fgets($fp);
       // $row = fread($fp, 2048);
        echo $row, "\r\n";
    }
    fclose($fp);
}

代碼2:對象

這裏採用了用fread()函數來控制每次讀取的數據大小,這個內存佔用和耗時,跟設置的每次讀取的數據大小有直接關係
內存

function test3($log_file) {
//    內存:656byte
//    時間:9.2053289413452秒
    $fp = fopen($log_file, 'r+');
    while(! feof($fp)) {
        $row = fread($fp, 2048);
        //echo $row;
    }
    fclose($fp);
}

代碼3:get

這種方式是用過用管道的方式打開文件,和代碼1對比,在同使用fgets()的狀況下,內存要比代碼1中佔用少一些。
cmd

function test2($log_file) {
//    內存:352byte
//    時間:13.38470697403秒
    $cmd = "cat {$log_file} 2>&1";
    $fp = popen($cmd, "r");
    while(!feof($fp))
    {
        $row = fgets($fp);
        echo $row, "\r\n";
    }
    pclose($fp);
}


另外還有使用fseek()函數等等,但都是在達到同一個目的,就是使得只有處理的數據讀取到內存中來減小內存佔用。

一樣也能夠使用php調用系統命令方式來達到目的,這裏沒有對那種方案進行測試。

附上我測試使用的函數:

$start = memory_get_usage();
$time1 = microtime(true);
test3($log_file);
$end = memory_get_usage();
$time2 = microtime(true);
$used = $end - $start;
$limit = $time2 - $time1;
echo "內存:", $used, "byte\r\n時間:", $limit, "秒\r\n";
相關文章
相關標籤/搜索