php进程的内存使用情况

时间:2016-02-18 09:00:38

标签: php linux memory

概要

简短的推荐(来自更多数据信息,请参阅答案)

为避免内存泄漏,您可以:

  1. 当它们变得无用时立即取消设置变量
  2. 您可以使用 xdebug 获取有关功能的内存消耗的详细报告并查找内存泄漏
  3. 您可以设置 memory_limit (例如设置为5Mb)以避免虚拟内存分配
  4. 问题

    什么php可以使用内存,除了库和变量? 我使用以下代码监视由变量及其~3Mb使用的内存:

    $vars = array_keys(get_defined_vars());
            $cnt_vars = count($vars);
            $allsize = 0;
            for ($j = 0; $j < $cnt_vars; $j++) {
    
                try
                {
                    $size = @serialize($$vars[$j]);
                    $size = strlen($size);
                }
                catch(Exception $e){
                    $str = json_encode($$vars[$j]);
                    $str = str_replace(array('{"','"}','":"','":'), '', $str);
                    $size = strlen($str);
                }
                $vars[$j] = array(
                    'size' => $size,
                    'name' => $vars[$j]
                );
                $allsize += $size;
            }
    

    和库需要~18Mb(libcurl等) 所以总计21 Mb,但

      

    pmap -x(进程)   显示,总内存消耗为kB:314028 RSS:74704 Dirty:59672

    所以,实际消费总量约为74Mb。 另外我在我的pmap中看到了一些带有[anon]映射的大块 对于使用此块的PHP?

    php版本: 5.5.9-1ubuntu4.14 php扩展:

    root@webdep:~# php -m
    [PHP Modules]
    bcmath
    bz2
    calendar
    Core
    ctype
    curl
    date
    dba
    dom
    ereg
    exif
    fileinfo
    filter
    ftp
    gd
    gettext
    hash
    iconv
    json
    libxml
    mbstring
    mcrypt
    mhash
    openssl
    pcntl
    pcre
    PDO
    pdo_pgsql
    pgsql
    Phar
    posix
    readline
    Reflection
    session
    shmop
    SimpleXML
    soap
    sockets
    SPL
    standard
    sysvmsg
    sysvsem
    sysvshm
    tokenizer
    wddx
    xml
    xmlreader
    xmlwriter
    Zend OPcache
    zip
    zlib
    
    [Zend Modules]
    Zend OPcache
    

4 个答案:

答案 0 :(得分:5)

PHP与编译为单个二进制文件的C或CPP代码不同。所有脚本都在Zend虚拟机中执行。大多数内存都由VM本身消耗。这包括加载的扩展使用的内存,PHP进程使用的共享库(.so文件)和任何其他共享资源。

我不记得确切的来源,但在某处我读到,PHP内部消耗了近70%的总CPU周期,而且只有30%的内容被用于代码(如果我错了,请纠正我)。这与内存消耗没有直接关系,但应该了解PHP的工作原理。

关于anon block我在另一个SO答案中找到了一些细节。答案是关于Java的,但同样适用于PHP。

  

Anon块是通过malloc或mmap分配的“大”块 - 请参阅   联机帮助页。因此,它们与Java堆无关(其他   而不是整个堆应该存储在这样的事实中   块)。

我建议禁用一些扩展程序。这应该可以节省一些未使用的内存。

答案 1 :(得分:3)

注意:这不是答案,而是OP要求的信息,但评论字段对于此来说太短了......这些是更多的工具如何调试这类问题。

Xdebug’s docs are pretty comprehensive,他们应该通过将文档复制到此处来告诉我如何更好地使用它。你给的脚本有点模糊,所以我自己没有做跟踪,但它会给你逐行的内存使用差异。

基本上将xdebug.show_mem_delta设置为1并启用Xdebug以生成函数跟踪,然后可以在文本编辑器中打开该函数跟踪以查看泄漏内存的内容究竟是什么部分。

然后你可以比较初始(或中间位置)总内存,看它与你看到的实际内存使用量有多大差异。

TRACE START [2007-05-06 14:37:26]
    0.0003     114112  +114112   -> {main}() ../trace.php:0

此处总内存为114112

如果差别很大,你可能想要使用类似shell_exec()的东西来获取所有行之间的实际内存使用量,然后输出它,然后你可以将该输出与Xdebug的内存输出进行比较以查看差异发生的地方。

如果差异来自脚本的第一行,那么罪魁祸首可能是PHP的扩展。如果有任何可疑的扩展名,请参阅php -m

答案 2 :(得分:2)

首先制作一个数组,调查正在进行的记忆

$startMemory = memory_get_usage();
$array = range(1, 100000);
echo memory_get_usage() - $startMemory, ' bytes';

一个整数是8 bytes(在64 bit unix machine上使用long类型)和100000 integers,因此您显然需要800000 bytes。这就像0.76 MB

此数组提供14649024 bytes。那是13.97 MB - 比估计值多出18倍

以下是所涉及的不同组件的内存使用情况的快速摘要:

                             |  64 bit   | 32 bit
---------------------------------------------------
zval                         |  24 bytes | 16 bytes
+ cyclic GC info             |   8 bytes |  4 bytes
+ allocation header          |  16 bytes |  8 bytes
===================================================
zval (value) total           |  48 bytes | 28 bytes
===================================================
bucket                       |  72 bytes | 36 bytes
+ allocation header          |  16 bytes |  8 bytes
+ pointer                    |   8 bytes |  4 bytes
===================================================
bucket (array element) total |  96 bytes | 48 bytes
===================================================
total total                  | 144 bytes | 76 bytes

同样,对于大型静态数组,如果我称之为:

$startMemory = memory_get_usage();
$array = new SplFixedArray(100000);
for ($i = 0; $i < 100000; ++$i) {
$array[$i] = $i;
}
echo memory_get_usage() - $startMemory, ' bytes';

结果为5600640 bytes

每个元素56 bytes,因此比普通数组使用的每个元素144 bytes小得多。这是因为固定阵列不需要桶结构。因此,每个元素只需要一个zval (48 bytes)和一个pointer (8 bytes),即可得到观察到的56 bytes

希望这会有所帮助。

答案 3 :(得分:0)

您看到的数字没有任何问题,您不应该将它们组合在一起,这只是“三倍”,您会看到单独列出的库的不同部分(只读,可执行,可写),您的数字是正确的。