欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

PHP错误:Allowed memory size of xxx bytes(二)

程序员文章站 2024-02-18 17:41:58
...
在上一篇文章中,针对查询数据表时候,php出现 “Allowed memory size of xxx bytes”的错误,在不修改php.ini配置的时候,用另外的函数来解决了这个问题,以牺牲部分性能的代价来换取内存空间,在这篇文章中,会说一下在读取文件的时候出现这个问题的解决思路。

在读取文件的时候,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()每次读取一行的结果,但是如果一行比较大的情况下,也会出现内存不够用的错误提示

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:

这种方式是用过用管道的方式打开文件,和代码1对比,在同使用fgets()的情况下,内存要比代码1中占用少一些。

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";