内存耗尽总是在同一行

时间:2013-04-17 12:18:16

标签: php performance memory optimization joomla

首先,我不是在寻找答案说"检查你的PHP内存限制"或"您需要添加更多内存"或者这些东西......我在一台专用机器上,有8GB的RAMS; 512MB是内存限制。我总是在一行中出现内存不足错误:

澄清:此部分代码属于Joomla! CMS。

function get($id, $group, $checkTime){
    $data = false;
    $path = $this->_getFilePath($id, $group);
    $this->_setExpire($id, $group);
    if (file_exists($path)) {
        $data = file_get_contents($path);
        if($data) {
            // Remove the initial die() statement
            $data   = preg_replace('/^.*\n/', '', $data); // Out of memory here
        }
    }
    return $data;
}

这是Joomla缓存的一部分......此函数读取缓存文件并删除阻止直接访问文件并返回其余数据的第一行。

如您所见,该行使用preg_replace删除缓存文件中的第一行,该行始终是:

<?php die("Access Denied"); ?>

我的问题是,在我看来,作为一个简单的过程(从文件内容中删除第一行),如果初始$数据很大,它会消耗大量内存吗?如果是这样的话,解决该问题的最佳方法是什么?我不介意使用没有die()行的缓存文件,我可以采取安全措施并阻止直接访问缓存文件。

我错了吗?

更新

正如帖子所建议的,正则表达式似乎比解决它们产生更多问题。我试过了:

echo memory_get_usage() . "\n";

在正则表达式之后,然后使用substr()尝试相同的语句。内存使用量的差异非常小。几乎没有。

对于你的贡献,我仍然试图找出这种情况发生的原因。

6 个答案:

答案 0 :(得分:5)

使用substr避免内存饥饿preg_replace(),如下所示:

$data = substr($data, strpos($data, '?>') + 3);

如果你可以通过使用其他字符串/数组函数执行相同的任务,一般建议不要使用正则表达式,正则表达式函数比核心字符串/数组函数更慢并且消耗更多内存。

这也在PHP文档中明确警告,请参阅一些示例:

http://www.php.net/manual/en/function.preg-match.php#refsect1-function.preg-match-notes http://www.php.net/manual/en/function.preg-split.php#refsect1-function.preg-split-notes

答案 1 :(得分:3)

不要使用字符串函数来替换巨大字符串中的内容。您可以循环浏览文件的行,然后在找到要查找的内容后中断。 在这里查看PHP文档:

http://php.net/manual/en/function.fgets.php

基本上是@cbuckley所说的:p

答案 2 :(得分:1)

如果您只想删除文件的第一行并返回其余文件,则应使用file

$lines = file($path);
array_shift($lines);
$data = implode("\n", $lines);

答案 3 :(得分:1)

您可以将file_get_contents()fopen()结合使用{{3>,而不是使用fgets()一次获取整个文件,这可能太大而无法运行正则表达式。 }})。此函数逐行获取文件。

然后,您可以选择在特定行上执行regexp。或者在您的情况下,只需跳过整行。

所以代替:

$data = file_get_contents($path);
if($data) {
    // Remove the initial die() statement
    $data   = preg_replace('/^.*\n/', '', $data); // Out of memory here
}

试试这个:

$fileHandler = fopen($path,'r');
$lineNumber = 0;
while (($line = fgets($fileHandler)) !== false) {
    if($lineNumber++ != 0) { // Skip the initial die() statement
        $data .= $line; // or maybe echo out $line directly so $data doesn't take up too much memory as well.
    }
}

答案 4 :(得分:0)

我建议你在包含缓存文件的文件中使用它:

define('INCLUDESALLOW', 1);

并在将包含的文件中:

if( !defined('INCLUDESALLOW') ) die("Access Denied");

然后只使用include代替file_get_contents。这将在包含的内容中运行PHP代码,但不是100%确定是否是您需要的。

答案 5 :(得分:0)

有时你会使用比分配的8 MB php更多的内存。如果通过提高代码效率而无法使用更少的内存,则可能需要增加可用内存。这可以通过两种方式完成。

可以在php.ini中将限制设置为全局默认值:

memory_limit = 32M

或者您可以在脚本中覆盖它,如下所示:

<?php
ini_set('memory_limit', '64M');
...

有关PHP内存限制的更多信息,您可以看到This SO questionini.memory-limit