PHP Imagick内存泄漏

问题描述 投票:9回答:4

我必须在PHP CLI上使用Imagick渲染某些东西。我已经注意到,每隔3-5天服务器内存就会满了,因此我什至无法通过ssh或ftp连接。

with memory_get_usage()我将内存泄漏降至脚本的imagick部分。脚本看起来像这样:

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

我销毁了图像参考,并取消设置了imagick和imagickDraw对象,但是脚本不会释放任何内存。setFillColor()方法占用最多的内存

我可以做点其他事情来释放imageick占用的空间吗?

image of the memory consumption

php memory-leaks imagick
4个回答
19
投票

imagick使用共享库,它的内存使用情况对于PHP来说是遥不可及的,因此调整PHP内存和垃圾回收将无济于事。

我本人也遇到了同样的问题,试图处理50(!)页3000x2000像素的多页tiff图像。解决方案是让imagick将其像素缓存放在磁盘上。

在创建Imagick对象之前添加此内容为我解决了问题:

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

目标是使imagick将其像素缓存放置在磁盘上,而不是RAM中。默认位置似乎是文件/ tmp / magick-XXnnnnn,因此请确保/ tmp不在shmfs / ramdisk上,或更改imagick使用的临时目录。

要调查的其他资源限制:imagick::RESOURCETYPE_DISKimagick::RESOURCETYPE_FILEimagick::RESOURCETYPE_AREA。它们在imagick::getResourceLimit() manual page中描述(在setResourceLimit()页面中不太好)。

在我的图像处理循环中,我有set_time_limit(300),因为脚本需要花费很多时间来处理这张巨大的图像(当解压缩时)。


EDIT:在最新版本中,不应将setResourceLimit()称为静态方法,而应在实际对象上调用,例如:
$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);

5
投票

我知道这很旧,但是我遇到了同样的问题,因此调用$im->clear()而不是$im->destroy()为我解决了内存泄漏。

根据documentation Imagick::destroy() has been deprecated in favor of Imagick::clear()。因此,应使用clear()


1
投票

xdebug无法帮助我..因此,我决定寻求其他解决方案。我想出了直接使用图像魔术的方法:

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

此解决方案比imagick的解决方案更平滑。但我不喜欢容易出错的代码。


0
投票

您可以使用它。

请注意,根据文档,clear()优先于destroy()以释放内存使用。

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

您还可以运行cron为您删除临时文件,否则您的服务器可能会崩溃。这不是php代码,而是命令行代码。

# linux command
find /tmp/ -name "magick-*" -type f -delete

# cron
45 * * * * find /tmp/ -name "magick-*" -type f -delete
© www.soinside.com 2019 - 2024. All rights reserved.