在上一篇文章中,針對查詢數據表時候,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";