php7 unset数组元素会不会释放内存

 针对这个问题, 我们先上一段代码. 

<?php
$memory2 = $memory3 = $memory4 = 0;
$data = [];
$memory = memory_get_usage();
foreach (range(1, 100000) as $key) {
	$data[$key] = str_repeat("1', 100);
}

$memory2 = memory_get_usage() - $memory;

foreach (range(1, 100000) as $key) {
	unset($data[$key]);
}

$memory3 = memory_get_usage() - $memory;

echo "memory2: " . $memory2, PHP_EOL;
echo "memory3: " . $memory3, PHP_EOL;

这段代码分别会输出3个内存使用情况. 分别记为memory2, memory3. 

memory2: 给数组设置10000个key, 给value字段设置100个1的字符串. 之后的内存. 

memory3: unset掉数据中所有的key之后的内存值. 

大家可以 猜一下, 会memory3会是0吗?

我先公布答案, memory3一定不会是0. 

不但不是0, 还是一个比较大的数, 超过6M. 如果你把上面的100000换得更大一点, 那这个值会更大。 为什么, 是内存泄露了吗?

不是的, 原来这是由PHP7的数组机制造成的。 PHP7为了提高数组的性能,把所有的zval结构内嵌在数组的Bucket内, 而且所有的Bucket是连续的。

此时假如要将其中的一个Bucket, 我们需要移动这个Bucket之后所有的元素,这样的效率显然是非常低的, PHP开发组当然也不会这么做。 那么当我们unset掉一个元素时php内核做了什么呢? 

很简单, 释放这个key所占用的内存, 然后将zval标记为IS_UNDEF. 结束. 

所以要说unset的时候释放内存了没有? 当前是释放了, key的内存也释放了, value的内存也释放了, 只是没有释放Bucket部分的内存。 并且这个Bucket只会越来越大。 

那么怎么才能释放这个Bucket的内存呢? 有办法. 主看下面的代码. 比上面的代码增加了一个memory4. 

$data的内容没有变, 但内存已经完全释放了。 所以在写一些守护进程时,如果用全局数组存放一些数组时需要注意一下内存的问题。 

 

 

 



文章来自: 本站原创
Tags:
评论: 0 | 查看次数: 41383