在上一篇文章中,针对查询数据表时候,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";