PHP实际使用了多少内存?

时间:2016-07-28 15:17:43

标签: php memory

我注意到,topps报告作为PHP流程的内存使用情况与流程本身认为使用的内容(使用memory_get_usage)之间存在很大差异

该进程实际使用了多少内存?

与我的某个应用程序一起运行以下代码时:

echo "Memory usage: " . pretty_bytes(memory_get_usage()) . PHP_EOL;
echo "Peak memory usage: " . pretty_bytes(memory_get_peak_usage()) . PHP_EOL;
echo "'Actual' memory usage: " . pretty_bytes(memory_get_usage(true)) . PHP_EOL;
echo "'Actual' peak memory usage: " . pretty_bytes(memory_get_peak_usage(true)) . PHP_EOL;

$ps_output = exec("ps --pid " . getmypid() . " --no-headers -o rss");

echo "'Memory usage according to ps: " . pretty_bytes(intval($ps_output) * 1000);

随机点的输出是:

Memory usage: 4.77 MB
Peak memory usage: 4.99 MB
'Actual' memory usage: 5.00 MB
'Actual' peak memory usage: 5.00 MB
Memory usage according to ps: 17.66 MB

在我的特殊情况下,这是一个问题,因为我正在运行相当多的工人和守护进程。

当我将PHP内存限制设置为例如每个守护进程128 MB,根据PHP自己的测量结果,进程只有达到128 MB才会被杀死。但是,根据ps,到那时,每个进程将使用大约200 MB。

3 个答案:

答案 0 :(得分:6)

memory_get_usage报告PHP进程分配的内存以运行脚本。 ps报告PHP进程本身使用的内存,其中包括用于脚本的内存。 PHP进程使用了​​许多外部库,它们都可以在没有PHP进程知道的情况下分配内存。

所以memory_get_usageps固有地衡量不同的事情,并应报告不同的数字。这一切都取决于你如何定义“实际内存使用”。据我所知,在您的情况下,您对PHP进程的内存使用更感兴趣。然后ps的输出对您更有意义。但是你可以很容易地发现即使ps报告的RSS值在现代操作系统和共享记忆的世界中也不是那么黑白。

另见:

答案 1 :(得分:5)

应该强调psmemory_get_usage(true)报告的确切值是什么。

ps -o rss报告实际的居民集大小。依赖于这个值是一个很大的陷阱,因为它不包括最终换掉的内存。通常,您需要 USS 唯一集大小,它基本上是非共享内存(请查看smem(8))。它是内核实际为该进程映射页面的非共享内存量,即在RAM或交换文件中实际存在非共享内存。这是你可以得到的最接近的真实"内存使用情况。 [另请参阅/proc/$PID/smaps详细概述,如IVO GELOV的答案中所述,您可以通过解析该虚拟文件从技术上统计您想要计算的内存。]

关于memory_get_usage(),它报告系统使用PHP的内部内存管理器实际分配的堆内存。这意味着,直接使用系统的其他内存管理器(mmap(2)malloc(3))的库不会在此处公开其内存使用情况。 [这就是为什么mysqlnd确实显示了很多内存使用量,而libmysqlclient没有 - 后者在内部使用malloc()。]

如果您将true作为第一个参数传递,即memory_get_usage(true),它将返回PHP内部内存管理器从系统中请求的内存总量。这个数字一般略有增加,但不会高于memory_get_usage(false)。它也是memory_limit INI设置与之比较的数字。

如果你想看看你可以运行多少工人,请注意PHP不会共享很多内存,除了内核可以共享库内存和opcache,它共享结构(操作码,类信息等)。因此,共享内存对您来说应该不重要。因此,最重要的价值应该是USS。

答案 2 :(得分:2)

在发布以下命令之一时,您可能会发现有趣的事情:

cat /proc/PID_NUMBER/smaps
pmap -d PID_NUMBER