0

我正在尝试从许多 html 文件中提取数据文件。为了快速完成,我不使用 DOM 解析器,而是简单的strpos(). 如果我从大约 200000 个文件生成,一切顺利。但是如果用更多的文件(300000)来做,它什么也不输出,并且会出现这种奇怪的效果:看下图。(上面是 CPU)在第一个(标记为红色)阶段,输出文件大小正在增长,一切似乎都很好。之后(标记为橙色)文件大小变为零并且内存使用量正在增长。(一切都是两次,因为我在中场休息时重新开始计算)

我忘了说我使用 WAMP。

我已经厌倦了未设置的变量,将循环放入函数中,使用 implode 而不是连接字符串,使用 fopen 而不是 filegetcontents 和垃圾收集......

第二阶段是什么?我是不是没记性了?是否有一些我不知道的限制(max_execution_time,memory_limit - 已被忽略)?为什么这个小程序会占用这么多内存?

加工

这是代码。

$datafile = fopen("meccsek2b.jsb", 'w');
for($i=0;$i<100000;$i++){
    $a = explode('|',$data[$i]);
    $file = "data2/$mid.html";
    if(file_exists($file)){
        $c = file_get_contents($file);
        $o = 0;
        $a_id = array();
        $a_h = array();
        $a_d = array();
        $a_v = array();
        while($o = strpos($c,'<a href="/test/',$o)){
            $o = $o+15;
            $a_id[] = substr($c,$o,strpos($c,'/',$o)-$o);
            $o = strpos($c,'val_h="',$o)+7;
            $a_h[] = substr($c,$o,strpos($c,'"',$o)-$o); 
            $o = strpos($c,'val_d="',$o)+7;
            $a_d[] = substr($c,$o, strpos($c,'"',$o)-$o);
            $o = strpos($c,'val_v="',$o)+7;
            $a_v[] = substr($c,$o,strpos($c,'"',$o)-$o);        
        }
        fwrite($datafile,  
            $mid.'|'.
            implode(';',$a_id).'|'.
            implode(';',$a_h).'|'.
            implode(';',$a_d).'|'.
            implode(';',$a_v).
            PHP_EOL);       
    }
}
fclose($datafile);

阿帕奇错误日志。(在 30 天内到期)

我想我发现了问题:

有一个无限循环,因为strpos()返回 0。分配的内存大小一直在增长,直到出现异常:

PHP Fatal error:  Out of memory 

Ensino 的注释对使用命令行非常有用,最终导致我提出这个问题

4

3 回答 3

0

您应该考虑从命令行运行脚本;这样您就可以在不深入查看错误日志的情况下捕获错误。
此外,如PHP 手册中所述,该strpos函数可能返回布尔值 FALSE,但也可能返回计算结果为 FALSE 的非布尔值,因此测试此函数返回值的正确方法是使用运算!==

while (($o = strpos($c,'<a href="/test/',$o)) !== FALSE){
...
}
于 2013-08-25T15:48:47.590 回答
0

CPU 峰值很可能意味着 PHP 正在进行垃圾收集。如果您想以更大的内存使用为代价获得一些性能,您可以通过 gc_disable() 禁用垃圾收集

查看代码,我猜你已经达到了file_get_contents读取一些大文件的地步,PHP 意识到它必须通过运行垃圾收集来释放一些内存才能存储它的内容。

如何处理这个问题的最佳方法是连续读取文件并按块处理它,而不是将它整个放在内存中。

于 2013-08-23T13:55:06.543 回答
0

大量数据正在进入系统内部缓存。当系统缓存的数据写入磁盘时,可能会对内存和性能产生影响。

有一个系统函数 FlushFileBuffers 要强制写入:请查看http://msdn.microsoft.com/en-us/library/windows/desktop/aa364451%28v=vs.85%29.aspxhttp:// winbinder.org/用于调用该函数。

(不过,除非有 Windows 错误,否则这不能解释空文件。)

于 2013-08-25T10:36:16.697 回答