用 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确实也优化了不少代码。

 

 

Tags: , , ,

发表评论