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";
相关文章
相关标签/搜索