Утечка памяти в PHP Imagick - PullRequest
       8

Утечка памяти в PHP Imagick

9 голосов
/ 03 апреля 2012

Я должен сделать что-то с помощью Imagick на PHP CLI. Я заметил, что каждые 3-5 дней память сервера переполняется, поэтому я даже не могу подключиться через ssh или ftp.

с помощью memory_get_usage () я объяснил утечку памяти вплоть до воображаемой части сценария. скрипт выглядит примерно так:

$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?

изображение потребления памяти

Ответы [ 3 ]

18 голосов
/ 11 октября 2012

imagick использует разделяемую библиотеку, и ее использование памяти недоступно для PHP, поэтому настройка памяти PHP и сборки мусора не поможет.

У меня была такая же проблема, я пытался обработать многостраничное изображение с 50 (!) Страницами размером 3000x2000 пикселей. Решение состоит в том, чтобы 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 поместил свой пиксельный кеш на диск, а не в оперативную память. Кажется, что местом по умолчанию являются файлы / tmp / magick-XXnnnnn, поэтому убедитесь, что / tmp отсутствует в shmfs / ramdisk, или измените временный каталог, используемый imagick.

Другие ограничения для расследования: imagick::RESOURCETYPE_DISK, imagick::RESOURCETYPE_FILE и imagick::RESOURCETYPE_AREA. Они описаны в справочной странице imagick :: getResourceLimit () (не очень хорошо на странице для 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);
4 голосов
/ 23 июня 2015

Я знаю, что это старый, но я столкнулся с той же проблемой, и вызов $im->clear() вместо $im->destroy() устранил утечку памяти для меня.

Согласно документации Imagick::destroy() has been deprecated in favor of Imagick::clear().Поэтому следует использовать clear().

1 голос
/ 04 апреля 2012

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

это решение работает намного лучше, чем воображаемое. но мне не нравится подверженный ошибкам код.

...