PHP 在取消设置后释放内存


PHP free memory after unset

它的测试小代码:

$strings = array('<big string here (2 Mb)');
$arr = array();
//--> memory usage here is 17.1Mb (checked by pmap)
echo memory_get_usage();//0.5Mb 
//(i know, that other 16.6Mb of memory used by process are php libraries)
for($i = 0; $i < 20; ++$i)
{
    $strings_local = array_merge($strings, array($i));
    $arr[$i] = $strings_local;
    unset($strings_local);
}
//--> memory usage here is 20.3Mb (checked by pmap)
echo memory_get_usage();//3.7Mb
//so, here its all ok, 17.1+3.2 = 20.3Mb
for($i = 0; $i < 20; ++$i)
{
    unset($arr[$i]);
}
//--> memory usage here is 20.3Mb (checked by pmap)
//BUT?? i UNSET this variables...
echo memory_get_usage();//0.5Mb

因此,似乎 php 不是可用内存,即使您unset()变量。取消设置后如何释放内存?

PHP 有垃圾收集器,它负责您的内存管理,它以几种不同的方式影响(进程的)内存使用。

首先,当检查进程外部进程的内存使用情况时,即使 PHP 看到一些内存被释放,也可能不会将其释放回操作系统,以用于与内存分配相关的优化目的。这减少了连续释放和分配的开销,这在 GC'd 语言中更容易发生,因为分配过程对实际程序不可见。

因此,即使手动调用gc_collect_cycles(),内存也可能根本不会释放到操作系统,而是重新用于将来的分配。这导致PHP看到的内存使用量比实际使用的进程要小,这是由于一些早期的大保留,这些保留永远不会释放回操作系统。

其次,由于垃圾回收的性质,在被程序标记为未使用后,内存可能不会立即释放。调用gc_collect_cycles()将使内存立即释放,但应该将其视为不必要的,并且如果您的脚本中有逻辑(或 PHP 泄漏中的某些内容)内存泄漏,则不起作用。

为了了解正在发生的事情,逐行检查(例如使用Xdebug的函数跟踪)可以让您更好地了解PHP(或者更确切地说,您的程序)如何查看内存使用情况。

将其与进程外部的逐行检查(例如pmap命令)相结合,可以判断 PHP 在保留内存后的任何时候是否真的释放了任何内存。