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