用 vld 神器,来解疑一段诡异的php代码
今天公司技术群抛出一个问题。
for ($i = 0; $i < 1000000; $i++) {
$array = ['a' => $i, 'b' => $i];
foreach ($array as $key => $val) {
true && $array[$key] = trim($val);
}
if ($i % 10000 == 0) {
$memory = round(memory_get_peak_usage(TRUE) / pow(1024, 2), 2);
echo "$i $memory\n";
}
}
开启opcache时,该运行代码内存会占用会越来越大。但删除行4的 true && 或 关闭 opcache 内存都是占用很小不会增大。在测试的PHP 5.4和7.0均存在。
可猜到,应该是变量没有被释放导致。为啥会这样呢?
只好拿出压箱底的神器—— vld,上次用也是第一次用是n年前了,差点忘记她的名字。
这是一个可以看php运行的opcode的php扩展,可以在找到php语言级别中一些迷惑。
看看
#1 opcache close, mem ==
5 14 > JMPZ_EX ~10 <bool>, ->20
15 > SEND_VAR !3
16 DO_FCALL 1 $12 'trim'
17 ASSIGN_DIM $11 !1, !2
18 OP_DATA $12, $13
19 BOOL ~10 $11
20 > FREE ~10
#2 opcache open, mem ++
5 13 SEND_VAR !3
14 DO_FCALL 1 $1 'trim'
15 ASSIGN_DIM $2 !1, !2
16 OP_DATA $1, $2
#3 opcache open & no and, mem==
5 13 SEND_VAR !3
14 DO_FCALL 1 $1 'trim'
15 ASSIGN_DIM !1, !2
16 OP_DATA $1, $2
对比上面看出(倒数第二列是 return )
内存的增加就在于ASSIGN_DIM 后有返回值,而且没有被释放。至于为啥没释放??我也布吉岛啊~
同时对比代码1、2可以看出,opcache确实也优化了不少代码。
发表评论