【问题标题】:Why GD doesn't release memory upon imagedestroy()?为什么 GD 在 imagedestroy() 时不释放内存?
【发布时间】:2015-11-26 00:24:49
【问题描述】:

我需要一个 PHP CLI 脚本来通过 GD 函数进行各种图像转换。图像很大,所以我需要尽可能多地压缩内存。但是,当被询问时,imagedestroy() 似乎不会释放内存。

考虑以下演示脚本'test.php':

    #!/usr/bin/php5
    <?php

    $memory = [0=> memoryCheck()];
    $res1 = imagecreatetruecolor(8192, 4096);
    memoryReport('Res1 created');
    $res2 = imagecreatetruecolor(8192, 4096);
    memoryReport('Res2 created');
    imagedestroy($res1);
    memoryReport('Res1 destroyed');
    imagedestroy($res2);
    memoryReport('Res2 destroyed');

    // memory reporting functions follow:
    function memoryCheck()
    {
        return (int) trim(substr(shell_exec('free -b'), 166, 11));
    }

    function format($value)
    {
        $val = \abs($value);
        $unit=array('B','kiB','MiB','GiB','TiB','PiB');
        return @round($val/pow(1024,($i=floor((($val==0)?0:log($val,1024))))),2).' '.$unit[$i];
    }

    function memoryReport($msg)
    {
        global $memory;

        $start = $memory[0];
        $prev = end($memory);
        $now = memoryCheck();

        echo sprintf("%s: %s (%s)\n", 
                        $msg, 
                        format($now-$start), 
                        (($diff=$now-$prev) <0) ? '-'. format($diff) : '+'. format($diff)
                    );
        $memory[] = $now;
    }
    ?>

让我们通过以下命令运行它:

free -m;./test.php;free -m

示例结果:

                 total       used       free     shared    buffers     cached
    Mem:          7890       7072        818        561        218       2497
    -/+ buffers/cache:       4355       3534
    Swap:         8299          0       8299
    Res1 created: 109.76 MiB (+109.76 MiB)
    Res2 created: 218.77 MiB (+109.01 MiB)
    Res1 destroyed: 218.9 MiB (+140 kiB)
    Res2 destroyed: 888 kiB (-218.04 MiB)
                 total       used       free     shared    buffers     cached
    Mem:          7890       7072        817        561        218       2498
    -/+ buffers/cache:       4356       3534
    Swap:         8299          0       8299

如您所见,创建一张图片需要 109-110MB。创建第二个后,我们有双倍的用完。但是先销毁并不会释放内存。只有在两个图像都被销毁后,所有资源的内存才会被释放。

为什么?我忽略了什么吗?我该怎么做才能修改它?

更新: 我添加了将 $res1 设置为 null,然后完全取消设置。代码:

    $memory = [0=> memoryCheck()];
    $res1 = imagecreatetruecolor(8192, 4096);
    memoryReport('Res1 created');
    $res2 = imagecreatetruecolor(8192, 4096);
    memoryReport('Res2 created');
    imagedestroy($res1);
    memoryReport('Res1 destroyed');
    $res1 = null;
    memoryReport('Res1 is null');
    unset($res1);
    memoryReport('Res1 is unset');
    imagedestroy($res2);
    memoryReport('Res2 destroyed');

现在的结果是:

    Res1 created: 109.48 MiB (+109.48 MiB)
    Res2 created: 219.33 MiB (+109.85 MiB)
    Res1 destroyed: 219.5 MiB (+168 kiB)
    Res1 is null: 220.15 MiB (+668 kiB)
    Res1 is unset: 220.38 MiB (+232 kiB)
    Res2 destroyed: 2 MiB (-218.36 MiB)

另外,我添加了

    gc_collect_cycles();
    memoryReport('GC collect');

就在 imagedestroy($res2); 之前然后事情变得奇怪了:

    Res1 created: 109.59 MiB (+109.59 MiB)
    Res2 created: 219.08 MiB (+109.5 MiB)
    Res1 destroyed: 219.21 MiB (+132 kiB)
    Res1 is null: 219.36 MiB (+148 kiB)
    Res1 is unset: 219.75 MiB (+408 kiB)
    GC collect: 220.57 MiB (+836 kiB)
    Res2 destroyed: 220.46 MiB (-108 kiB)

根据'free'命令,只有在脚本结束后才会释放内存。

【问题讨论】:

  • imagedestroy() 只会释放内存以供在 PHP 中使用。它不一定会将内存释放回系统。 PHP 以块的形式从系统中分配内存。如果 $res1 使用的块碰巧包含来自 $res2 的内容(或任何其他变量),则它不会被释放。除了尝试更改这些资源的创建顺序之外,您几乎无能为力。
  • @cleong 你应该发布这条评论作为答案。
  • 确实,请这样做,以便我可以奖励您的回答:)
  • @cleong:请发表您的评论作为答案,以便我奖励您的答案:)

标签: php memory gd


【解决方案1】:

我想知道是不是 GC...尝试在 imagedestroy() 之后运行 gc_collect_cycles()。远射,但你永远不知道......

【讨论】:

  • 查看更新的问题。添加这个 gc_collect_cycles() 实际上让事情变得更糟。我更困惑了。
  • 嗯...对不起,我没有想法。祝你好运!
猜你喜欢
  • 2013-01-12
  • 2014-12-27
  • 1970-01-01
  • 1970-01-01
  • 2013-12-23
  • 2018-06-10
  • 1970-01-01
  • 2016-02-23
相关资源
最近更新 更多