PHP实际使用了多少内存?
PHP实际使用了多少内存?
我注意到,对于PHP进程,top
或ps
报告的内存使用情况与进程本身认为它正在使用的内存(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时,进程只会在它们达到128 MB时根据PHP自己的测量被杀掉。然而,根据ps
,到那时进程将使用约为每个200 MB。
memory_get_usage
报告 PHP 进程分配给运行你的脚本的内存。 ps
报告由 PHP 进程本身使用的内存,包括用于你的脚本的内存。PHP 进程使用许多外部库,这些库都可以在 PHP 进程不知情的情况下分配它们的内存。
因此,memory_get_usage
和 ps
内在地测量不同的内容,并且应该报告不同的数字。这一切都取决于你如何定义“实际内存使用情况”。我理解,在你的情况下,你更关心 PHP 进程使用的内存。那么 ps
的输出对你更有意义。但你可以轻松地发现,即使是 ps
报告的 RSS 值在现代操作系统和共享内存的世界也并不是非黑即白的。
还可参见:
应该强调的是ps
和memory_get_usage(true)
报告的确切值。\n\nps -o rss
报告实际的Resident Set Size。 依赖此值会非常困难,因为它不包括最终交换出的内存。 通常,您想要USS,即独特的设置大小,这基本上是未共享的内存(请查看smem(8)
)。 它是内核实际为该进程映射页面的未共享内存量,即RAM或交换文件中实际存在的未共享内存量。 这是您可以获得“真正”内存使用情况的最接近的值。[还可以参考IVO GELOV提供的答案中提到的/proc/$PID/smaps
进行详细概述,在其中可以通过解析该虚拟文件来技术上计算您要计算的内存。]\n\n关于memory_get_usage()
,它报告了由使用PHP内部内存管理器的系统实际分配的堆内存。这意味着直接使用其他内存管理器(mmap(2)
或malloc(3)
)的库不会在此处显示其内存使用情况。[例如,这就是为什么mysqlnd显示了很多内存使用情况,而libmysqlclient不显示的原因 - 后者在内部使用malloc()
。]\n\n如果将第一个参数设置为true
,即memory_get_usage(true)
,它会返回PHP内部内存管理器从系统要求的内存总量。这个数字通常稍微高于memory_get_usage(false)
,但不是很高。它还是与memory_limit
INI设置进行比较的数字。\n\n如果您想要查看可以运行多少工作程序,请注意PHP并不共享太多内存,除了内核可能共享库内存和opcache,后者共享结构(操作码,类信息等)。 因此,共享内存对您而言不那么重要。 对于您来说,最重要的值应该是USS。