php 进程的内存使用情况


Memory usage of php process

总结


简短建议(来自更多数据信息,请参阅答案)

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

  1. 当变量变得无用时立即取消设置变量
  2. 您可以使用 xDebug 按函数详细报告内存消耗并查找内存泄漏
  3. 您可以设置 memory_limit(例如 5Mb)以避免虚拟内存分配

问题

除了库和变量之外,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 脏:59672

因此,总实际消耗量为 ~74Mb。我还在我的 pmap 中看到一些带有 [anon] 映射的大块用于使用此块的 PHP 是什么?

PHP 版本: 5.5.9-1Ubuntu4.14PHP 扩展:

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

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

我不记得确切的来源,但我在某处读到,近 70% 的总 CPU 周期被 PHP 内部消耗,只有 30% 用于您的代码(如果我在这里错了,请纠正我)。这与内存消耗没有直接关系,但应该给出一个关于PHP如何工作的想法。

关于匿名块,我在另一个SO答案中找到了一些细节。答案是关于Java的,但同样应该也适用于PHP。

负离子块是通过malloc或mmap分配的"大"块 - 请参阅 手册页。因此,它们与 Java 堆无关(其他 而不是整个堆应该存储在这样一个 块)。

  • 这是SO答案的实际链接https://stackoverflow.com/a/1483482/1012809

  • 有关匿名内存页(匿名)的更多详细信息,请查看此文章https://techtalk.intersec.com/2013/07/memory-part-2-understanding-process-memory/

  • 另请查看此幻灯片共享,了解有关 PHP 内存管理的更多详细信息http://www.slideshare.net/jpauli/understanding-php-memory

我建议禁用一些扩展。这应该为您节省一些未使用的内存。

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

Xdebug 的文档非常全面,他们应该通过复制他们的文档来告诉如何使用它比我更好的方法。您提供的脚本有点模糊,所以我没有自己进行跟踪,但它会为您提供内存使用情况的逐行差异。

基本上将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

首先创建一个数组,以调查它正在占用的内存

$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 - 比估计的多十八倍

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

                             | 64 位 |32 位---------------------------------------------------兹瓦尔 | 24 字节 |16 字节+ 循环气相色谱信息 |  8 字节 | 4 字节+ 分配标头 | 16 字节 | 8 字节===================================================兹瓦尔 (价值) 总计 | 48 字节 |28 字节===================================================铲斗 | 72 字节 |36 字节+ 分配标头 | 16 字节 | 8 字节+ 指针 |  8 字节 | 4 字节===================================================存储桶(数组元素)总计 | 96 字节 |48 字节===================================================总计 |144 字节 |76 字节

同样,对于大型静态数组,如果我调用如下:

$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

希望这会有所帮助。

你看到的数字没有问题,你不应该组合它们,这只是"三倍",你看到不同的部分(只读、可执行、可写)单独列出的库,你的数字是正确的。

相关文章: