【问题标题】:where is the memory leak in this PHP code snippet?这个 PHP 代码片段中的内存泄漏在哪里?
【发布时间】:2013-02-08 10:49:40
【问题描述】:

我有一个 PHP 代码 sn-p 读取 apache 访问日志进行处理。我已将代码精简到这几行,但仍然发现泄漏。 PHP 进程不断占用越来越多的内存,尽管 echo memory_get_usage() 每次都报告 11Mb。

在 Ubuntu 12 机器上使用 PHP 5.3.6 运行。 Ubuntu 上的 PHP 5.2 解决了问题。

$logDir = opendir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tempLog');
while (($file = readdir($logDir)) !== false) {
    echo($file . PHP_EOL);

    $filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tempLog' . DIRECTORY_SEPARATOR . $file;
    $fhandle = fopen($filePath, 'r');
    fseek($fhandle, 0);

    while(!feof($fhandle)) {
        $line = fgets($fhandle);
    }

    fclose($fhandle);
    echo('Finished reading!' . PHP_EOL);
    echo('Memory usage: ' . memory_get_usage() . PHP_EOL . PHP_EOL);
    system('cat /proc/' . getmypid() . '/status | grep VmSize');
}

编辑:添加了此脚本的示例输出: EDIT2:添加了 VM 大小

access.log.2
Finished reading!
Memory usage: 11303616
VmSize:       54972 kB

access.log.19
Finished reading!
Memory usage: 11303616
VmSize:       55896 kB

access.log.23
Finished reading!
Memory usage: 11303616
VmSize:       81372 kB

access.log.41
Finished reading!
Memory usage: 11303616
VmSize:       93120 kB

access.log.31
Finished reading!
Memory usage: 11303616
VmSize:      107508 kB

access.log.28
Finished reading!
Memory usage: 11303616
VmSize:      112128 kB

access.log.5
Finished reading!
Memory usage: 11303616
VmSize:      112920 kB

..
Finished reading!
Memory usage: 11303592
VmSize:      112920 kB

.
Finished reading!
Memory usage: 11303592
VmSize:      112920 kB

内存泄漏可能在哪里?以及如何避免它?

【问题讨论】:

  • 作为 WAG,我猜想应该归咎于 while 循环。可能与fgets有关。
  • 作为妻子和女朋友? en.wikipedia.org/wiki/WAGs
  • Apache 访问日志可能会变得非常大,您尝试解析的日志有多大?
  • @mike 这与 fgets 无关。你试过另一个php版本吗?
  • 你提到你的同事和 Crozin 一样没有问题,他们测试了哪些 PHP 版本?如果您认为不是 PHP 版本问题,您可以尝试使用 SplFile api:php.net/manual/en/spl.files.php

标签: php memory-leaks


【解决方案1】:

默认情况下,PHP 不进行垃圾收集(这似乎来自手册的略读)。您可以做几件事。

1) 使用 gc_enable() 启用 GC。您可以使用 gc_collect_cycles() 强制 GC 通过。

2) 使用unset($line) 显式销毁$line

【讨论】:

  • 我刚刚意识到这可能无法解决您的问题。要尝试的另一件事是使用TRUE 参数调用memory_get_usage 以从操作系统而不是PHP 的内部计数器获取使用情况。他们的分配器中可能存在错误。
  • 很好的建议,但都没有帮助。传入 TRUE 也没有什么不同......相反,它报告的内存量略有不同,但每次迭代仍然相同
  • 你没有得到不同的衡量标准吗?您如何从操作系统获取内存大小?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 2012-05-22
  • 1970-01-01
  • 2011-01-01
相关资源
最近更新 更多