PHP Imagick memory leak

后端 未结 4 702
庸人自扰
庸人自扰 2020-12-09 20:34

I have to render something with Imagick on PHP CLI. I have noticed that every 3-5 days the server memory gets full, so i can\'t even connet via ssh or ftp.

with memo

相关标签:
4条回答
  • 2020-12-09 21:06

    You can use this.

    Note that clear() is preferred over destroy() according to the docs to release memory use.

    // clear temp files
    $imagick_image->clear(); // in your case "$img->clear();"
    

    You can also run a cron to delete the temp files for you, otherwise your server could crash. This is not php code, it is command line code.

    # linux command
    find /tmp/ -name "magick-*" -type f -delete
    
    # cron
    45 * * * * find /tmp/ -name "magick-*" -type f -delete
    
    0 讨论(0)
  • 2020-12-09 21:22

    I know this is old but I ran into the same problem and calling $im->clear() instead of $im->destroy() fixed the memory leak for me.

    According to the documentation Imagick::destroy() has been deprecated in favor of Imagick::clear(). So clear() should be used.

    0 讨论(0)
  • 2020-12-09 21:31

    imagick uses a shared library and it's memory usage is out of reach for PHP, so tuning PHP memory and garbage collection won't help.

    I had the same problem myself, trying to handle a multi-page-tiff image with 50 (!) pages of 3000x2000 pixels. The solution is to have imagick put its pixel cache on disk.

    Adding this prior to creating the Imagick object solved the problem for me:

    // pixel cache max size
    IMagick::setResourceLimit(imagick::RESOURCETYPE_MEMORY, 256);
    // maximum amount of memory map to allocate for the pixel cache
    IMagick::setResourceLimit(imagick::RESOURCETYPE_MAP, 256);
    

    The goal is to make imagick put its pixel cache on disk instead of in RAM. The default place seems to be files /tmp/magick-XXnnnnn, so make sure /tmp is not on shmfs/ramdisk, or change the temp directory imagick uses.

    Other resouce limits to investigate: imagick::RESOURCETYPE_DISK, imagick::RESOURCETYPE_FILE, and imagick::RESOURCETYPE_AREA. They are described in the imagick::getResourceLimit() manual page (not so well in the page for setResourceLimit()).

    In my image handling loop, I have set_time_limit(300), since the script takes ages to process this huge (when uncompress) image.


    EDIT : In recent versions, setResourceLimit() should not be called as a static method, but on the actual object instead, such as:

    $im->setResourceLimit(imagick::RESOURCETYPE_MEMORY, 256);
    $im->setResourceLimit(imagick::RESOURCETYPE_MAP, 256);
    $im->setResourceLimit(imagick::RESOURCETYPE_AREA, 1512);
    $im->setResourceLimit(imagick::RESOURCETYPE_FILE, 768);
    $im->setResourceLimit(imagick::RESOURCETYPE_DISK, -1);
    
    0 讨论(0)
  • 2020-12-09 21:31

    xdebug wasn't able to help me.. so i decided do look out for another solution. i came up with using image magic direct:

    $sourceImg = 'source.png';
    $destImg = 'dest.png';
    $background ='#00ff00';
    
    $command = "convert {$sourceImg}";
    $out = array();
    
    for($i=1;$i<=5;$i++){
        $command .= " -fill \"{$background}\" ";
        $command .= " -draw 'rectangle {$x1},{$y1} {$x2},{$y2}'";
    } 
    
    $command .= " {$destImg}";
    exec($command,$out);
    

    this solutions works way smoother then the imagick one. but i don't like the error-prone code.

    0 讨论(0)
提交回复
热议问题