【问题标题】:php memory_get_usage(true) vs top %MEMphp memory_get_usage(true) vs top %MEM
【发布时间】:2012-09-20 06:49:27
【问题描述】:

我有一个使用 AWS Dynamo PHP API 用 PHP 编写的脚本。它运行一个很长的循环,从发电机中提取大量数据,然后对其进行处理。

当我使用“top”查看进程时,我可以看到“php”进程使用的内存使用情况

在我的脚本循环中,我打印 memory_get_usage(true) 的结果

当我运行我的测试时,这两个值甚至都不相似......

他们应该是吗?如果不是为什么不呢?

在我的测试中,我有一个 1.7gb 内存的服务器,我将 php.ini 的 memory_limit 设置为 64M。我还在脚本开始时调用 gc_enable(),并在每个循环之间调用 gc_collect_cycles(),希望强制进行垃圾回收。

当我使用 'top' 观看我的 php 脚本时,我可以看到 %MEM 不断上升,直到它最终超过 95% 并且 linux 杀死了 php 进程,我通过查看 'dmesg' 知道这一点。当我查看循环每次迭代的打印输出时,memory_get_usage(true) 报告的内存使用量永远不会超过 50mb。

Linux 认为脚本使用了将近 1.7gb,php 认为它只使用了 50mb!

发生了什么事?

即使脚本有内存泄漏,我也不明白为什么 memory_get_usage(true) 不占内存...

更新

花了一些时间注释掉我在循环中运行的处理的各个部分后,我发现如果我删除以下代码:

class cMyClass {
    public static function static_cmp_fn(&$a, &$b) {
        if ($a['att'] == $b['att']) { return 0; }
        $ret = ($a['att'] < $b['att']) ? -1 : +1;
        return $ret;
    }
    function DoProcessing(){
        $sort_fn = array("cMyClass", "static_cmp_fn");
        usort($this->m_dictToSort, $sort_fn); 
        unset($sort_fn);
    }

}

php 永远不会吃掉所有的系统内存。在我看来,usort 正在泄漏内存,我不知道为什么。我不明白的是为什么 PHP 会报告有关它正在使用多少内存的错误信息...

有什么想法吗?

【问题讨论】:

  • 显示memory_get_peak_usage()的输出。
  • 当我将它添加到我的日志中时,它会为循环的每次迭代打印出大约 75mb,这与 top 报告的 php 使用的 95% 的 1.7gb 系统内存完全不同..
  • 那你的php版本或者你使用的扩展有问题。 PHP 永远不会让用户分配超过 memory_limit。
  • 你的 static_cmp_fn 里面有什么?

标签: php memory memory-management memory-leaks


【解决方案1】:

花了一些时间注释掉我在循环中运行的处理的各个部分后,我发现如果我删除以下代码:

$sort_fn = array("cMyClass", "static_cmp_fn");
usort($this->m_dictToSort, $sort_fn); 

php 永远不会吃掉所有的系统内存。在我看来,usort正在泄漏内存,我不知道为什么。

显然是这样。见手册:

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

"这里有几个例子提倡使用'create_function'进行排序,由于usort的限制,这很容易使用。但是要注意这种方法-创建的函数不会在结束时被释放排序例程,这会造成内存泄漏。因此,可能永远不应该使用这种方法。”

array() 方法似乎做了类似的事情。你可以声明一个包装函数,在外部调用你的方法,也许?

更新

试图构建一个小测试用例来看看会发生什么。到目前为止,我无法重现泄漏;也许有更多关于static_cmp_fn() 的功能以及m_dictToSort 的结构的数据。一个简单的比较不会触发任何奇怪的事情。也不会在循环内分配字符串、数组或对象。垃圾收集器将它们杀死,内存仍然很低。

我会通过调用 another 函数来进一步限制问题,该函数根本不排序,或者进行非常基本的排序,以查看问题是否在于 usort 做一些有趣的事情它是可调用的,正如我所想的那样(它似乎没有,而且我错了)或者比较函数内部发生了一些有趣的事情。

【讨论】:

  • 我想知道这一点,并尝试添加一个 unset($sort_fn) 没有任何运气。文档中没有任何内容表明传入提供类名和静态函数的数组与使用 php 的“create_function”fn 动态创建函数相同
  • array() 中的回调与 create_function 不同。我会小心引用没有证据的旧 cmets。
  • 好吧,不检查 PHP 代码,我们不知道 usort() 对数组做了什么。但你是对的;我会做一些实验。
  • usort() 实现从第 635 行开始。祝你好运:pastebin.ca/2238002
猜你喜欢
  • 2013-07-08
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
  • 1970-01-01
  • 2013-08-08
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
相关资源
最近更新 更多