PHP的内存泄漏

所谓的内存泄漏就是忘记释放内存,导致进程所占用的物理内存持续增长。

FPM 的黑魔法 - php_request_shutdown

在 传统运行在 FPM 下的 PHP 代码是没有“内存泄漏”一说的。在 PHP 内核有一个关键函数叫做 php_request_shutdown,此函数会在请求结束后,把请求期间申请的所有内存都释放掉。这从根本上杜绝了内存泄漏,极大的提高了 PHPer 的开发效率,同时也会导致性能的下降,例如单例对象,没必要每次请求都重新申请释放这个单例对象的内存。而这也是 Swoole 等 Cli 方案的优势之一,因为 Cli 请求结束不会清理内存。

Cli 下的内存泄漏

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 12288 bytes)

相信 PHPer 都遇见过这个报错,这是由于向 PHP 申请的内存达到了上限导致的,在 FPM 下一定是因为这次请求有大内存块申请,例如 SQL 查询返回一个超大结果集,但在 Cli 下报这个错大概率是因为你的 PHP 代码出现了内存泄漏。

常见的泄漏姿势有:

  • 向类的静态属性中追加数据,例如:
1
2
3
4
5
//不停的调用foo() 内存就会一直涨
function foo()
{
ClassA::$pro[] = "the big string";
}
  • 向 $GLOBAL 全局变量中追加数据,例如:
1
2
3
4
5
//不停的调用foo() 内存就会一直涨
function foo()
{
$GLOBAL['arr'][] = "the big string";
}
  • 向函数的静态变量中追加数据,例如:
1
2
3
4
5
6
//不停的调用foo() 内存就会一直涨
function foo()
{
static $arr = [];
$arr[] = "the big string";
}