php7 unset数组元素会不会释放内存
作者:admin 日期:2018-08-31
针对这个问题, 我们先上一段代码.
<?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的内容没有变, 但内存已经完全释放了。 所以在写一些守护进程时,如果用全局数组存放一些数组时需要注意一下内存的问题。
订阅
array_unshift的性能问题
awk 切分nginx日志中的字段

文章来自:
Tags: