PHP Imagick memory leak

你。 提交于 2019-12-18 03:36:05

问题


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 memory_get_usage() i narrwoed the memory leak down to the imagick part of the script. the script looks something like this:

$sourceImg = 'source.png';
$destImg = 'dest.png';
$background ='#00ff00';

$im = new Imagick();
$im->pingImage($sourceImg);
$im->readImage($sourceImg); 
$draw = new ImagickDraw();

for($i=1;$i<=5;$i++){
    $draw->setFillColor( $background);
    $draw->rectangle( 10*$i+5, 10, 10*$i+10, 20);
} 

$im->drawImage( $draw );
$im->writeImage( $destImg );
$im->destroy();

unset($im,$draw);

I destroy the image reference, and unset the imagick and imagickDraw object, but the script won't release any memory. The setFillColor() method takes the most memory

Can i do something else to free the space used by imageick?

image of the memory consumption


回答1:


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);



回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/9993085/php-imagick-memory-leak

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!