【问题标题】:PHP not clearing RAM when finished完成后PHP不清除RAM
【发布时间】:2014-09-21 01:08:05
【问题描述】:

下面是我试图完成以查看我们 PBX 上的日志的代码。它运行良好,对日志文件进行排序,显示所有数据等。问题是一旦完成,它会在内存中保留大量数据(数百 MB)。完成后我需要清除它,但不知道如何。如果它运行了几次,它会从服务器中吸走所有的 RAM,然后我们就会开始出错。提前致谢!

<!DOCTYPE html>
<html>
<title>Call Search</title>
<body>

<?php
function getBetween($var1, $var2, $pool)
{
        $temp1 = strpos($pool, $var1) + strlen($var1);
        $result = substr($pool, $temp1, strlen($pool));
        $dd=strpos($result, $var2);
        if($dd == 0){$dd = strlen($result);}
        return substr($result, 0, $dd);
}

if(!isset($_POST['phonenum']) && !isset($_POST['WantedCallID']))
{
        echo '<form action="test.php" method="post">';
            echo '<h4>Please enter the number you wish to search for...</h4><input     type="text" name="phonenum">';
    echo '<input type="submit" value="Go">';
    echo '</form>';
}

else if(isset($_POST['WantedCallID']))
{
   $counter = 0;
   $logfile="calllog";
   while (file_exists("/var/log/".$logfile))
   {
      if($counter==0){$logfile="calllog";}
      else{$logfile="callog.".$counter;}
      $path = "/var/log/".$logfile;
      $logtoarray = file($path);
      foreach ($logtoarray as $linenumber => $line)
      {
         if(strpos($line, "[".$_POST['WantedCallID']."]") !== false){echo $line."    <br>";}
      }
   $counter++;
   }
}

else
{
   $counter = 0;
   $logfile="calllog";
   $arrayCounter = 0;
   while (file_exists("/var/log/".$logfile))
   {
      if($counter == 0){$logfile = "calllog";}
      else{$logfile="calllog.".$counter;}
      $path = "/var/log/".$logfile;
      if(file_exists($path))
      {
         $logtoarray = file($path);
         $oldCallId = "";
         $currentCallId = "";
         foreach ($logtoarray as $linenumber => $line)
         {
             if(strpos($line, $_POST['phonenum']) !== false && strpos($line, "VERBOSE[") !== false)
             {
                    $currentCallId = getBetween("VERBOSE[", "]", $line);
                if($currentCallId !== $oldCallId)
                {
                   $callIdArray[$arrayCounter] = "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."\n";
                   echo "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."<br>";
               $oldCallId = $currentCallId;
            }
        }
        $arrayCounter++;
     }
  }
  else{break;}
  $counter++;
   }
   echo '<form action="test.php" method="post">';
   echo '<h4>Please enter the call ID you wish to search for...</h4><input type="text" name="WantedCallID">';
   echo '<input type="submit" value="Go">';
   echo '</form>';
}

$variables = array_keys(get_defined_vars());
foreach($variables as $variable) {
    unset(${"$variable"});
}
unset($callIdArray);
?>

</body>
</html>

【问题讨论】:

  • Alister 在他的回答中所说的是正确的,但是还有另一个因素:您在我认为是一个相当大的日志文件上使用 file()。这是您的内存膨胀开始的地方,您可以通过使用fopen()/fgets() 并以可管理的块迭代文件而不是将整个文件加载到内存中来显着减少内存占用一次。
  • 是的,这些文件通常非常大而且非常冗长。我们将致力于切换我们调用文件的方式。现在我们已经将“MaxRequestsPerChild”设置从 4000 调整到 1000,但这感觉就像我们只是在绕开这个问题,而不是正面处理它。它也没有清除它。

标签: php memory ram


【解决方案1】:

我假设您通过 Apache 服务器运行此脚本。这是一个相当普遍的问题,虽然我经常在调整图像大小时看到它。

一旦 Apache 子进程(运行 PHP 的进程)拥有了它的内存量,或者更常见的是 PHP,由于使用了大量数据而增加了,它没有方法可以将内存返回到操作系统。

相反,每个子进程都有MaxRequestsPerChild 设置。这可能设置为0 - 从不重新启动。如果膨胀的内存大小是一个问题,那么将其设置为几百或几千可能会很有用。在这么多请求之后,apache 子进程重新启动,因此所有捕获的内存 si 返回给操作系统,如果需要,一个新的子进程会启动。虽然重新启动进程时请求可能需要更长的时间,但释放内存会更有用。

【讨论】:

  • 我们已将其从 4000 降至 1000。任何时候 TOP 仅显示少于 10 个“/usr/sbin/httpd”进程。不确定这是否表明有多少正在运行。我们已经把它降到了 40 并且它也没有清除它。
【解决方案2】:

这是对代码的简单修改,它将一次读取一行日志文件,而不是将整个文件读入内存。

while (file_exists("/var/log/".$logfile))
{
    if($counter == 0){$logfile = "calllog";}
    else{$logfile="calllog.".$counter;}
    $path = "/var/log/".$logfile;
    if(file_exists($path))
    {
        $fh = fopen($path, 'r'); //change
        $linenumber = 0; //addition
        $oldCallId = "";
        $currentCallId = "";
        while( $line = fgets($fh) ) //change
        {
            $linenumber++; //addition
            if(strpos($line, $_POST['phonenum']) !== false && strpos($line, "VERBOSE[") !== false)
            {
                $currentCallId = getBetween("VERBOSE[", "]", $line);
                if($currentCallId !== $oldCallId)
                {
                    $callIdArray[$arrayCounter] = "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."\n";
                    echo "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."<br>";
                    $oldCallId = $currentCallId;
                }
            }
            $arrayCounter++;
        }
        fclose($fh); //addition
    }
}

【讨论】:

  • 非常有帮助,谢谢。你认为我们需要在末尾取消设置变量的部分吗?
  • 除非在您发布的内容结束后发生更多事情,否则永远不需要。 PHP 将自行取消设置变量并释放内存,这是 apache 工作人员 [mod_php 正在其中运行] 是没有实际将内存释放回系统的罪魁祸首。
  • 谢谢,这似乎已经解决了问题。如果我们对此有任何其他问题,我会回复。
猜你喜欢
  • 2017-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 2016-12-18
  • 1970-01-01
相关资源
最近更新 更多