性能专题 - 内存峰值

  • 作者:KK

  • 发表日期:2016.10.14


要点速读

新增变量或有新的运算时一般都会累加内存峰值,但unset变量后不会降低峰值,再新增变量,会利用一些旧变量空出的空间,所以峰值会增加得不明显


当一个进程启动后,进程可以向系统申请分配内存,比如接下来一个变量要占16B容量的话,就要申请足够的容量来装这个变量了

所以PHP在运行过程中根据程序计算的需要,不断地按需求情况向系统申请更多的内存容量,我们先看看下面这样的代码大概用了多少内存:

$a = [
	'11111111111111111111111111111111111111',
	'11111111111111111111111111111111111111',
	'11111111111111111111111111111111111111',
	'11111111111111111111111111111111111111',
	'11111111111111111111111111111111111111',
	'11111111111111111111111111111111111111',
	'11111111111111111111111111111111111111',
];
echo memory_get_peak_usage(); //这个函数可以获取内存峰值

我这里运行结果是输出了120216,表示直到调用memory_get_peak_usage函数的时候为止,操作系统一共为PHP进程分配了120216B内存,大概就是117KB

你的运行结果和我的不一定是一样的,看我们的环境具体情况,但误差不会很大,总不会是我得出117KB,而你你就得出2MB这样嘛


unset销毁变量后,内存峰值并不会下降

有些小有经验的程序员都觉得:我积极地去unset变量应该就能节省内存提高性能了

但你可能想错了,看看这个代码实验:

echo memory_get_peak_usage() . PHP_EOL; //120984

$b = [
	new stdClass(),
	new stdClass(),
	new stdClass(),
	get_declared_classes(),
	get_declared_classes(),
	get_declared_classes(),
	get_declared_classes(),
	get_declared_classes(),
	get_declared_classes(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
	get_defined_vars(),
];
echo memory_get_peak_usage() . PHP_EOL; //215576  新增个大数组后的峰值

unset($b);
echo memory_get_peak_usage(); //215600  都unset了变量,为什么峰值还是这么高?

对,为什么unset了还是那么高?继续往下


内存循环利用

unset一个变量后,PHP会将这个变量腾出的空间存到自己的“私房钱”里而不是交还给系统,此时系统一直认为“这个PHP进程就是用了很多内存”

如果再有新变量什么的,PHP就先看看“私房钱”能顶用多少,顶多少算多少,不够用再向系统申请新的内存

$a = [
	$_SERVER
];
echo memory_get_peak_usage() . PHP_EOL; //132320

$b = [
	new stdClass(),
	new stdClass(),
	new stdClass(),
	get_declared_classes(),
	get_defined_vars(),
];
echo memory_get_peak_usage() . PHP_EOL; //147048

//接下来如果新增$c会导致增加对吧!?
unset($a, $b);
echo memory_get_peak_usage() . PHP_EOL; //147048 销毁了峰值也不会下降
$c = [
	[
		$_SERVER,
	]
];
echo memory_get_peak_usage(); //147072

以上执行unset($a, $b)后再申请$c变量,内存峰值从147048增长到147072,共增长24B,但我可以保证$c变量里面的$_SERVER变量值内容不止24B

接下来尝试将unset语句注释掉,我看到的是从147000增长到147408,共增长408B

这里意味着什么?就是说当销毁a b两个变量后,腾出的空间用在c身上了,所以新增c时所扩展的内存空间仅只有24B

如果不执行unset的话,那就没私房钱可以花了