2012-04-03 5 views
6

PHP CLI에서 Imagick으로 무엇인가를 렌더링해야한다. 나는 3-5 일마다 서버 메모리가 가득 차서 ssh 나 ftp를 통해 연결할 수 없다는 것을 알아 챘다.PHP Imagick memory leak

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

답변

15

imagick은 공유 라이브러리를 사용하며 메모리 사용량이 PHP에 미치지 못하므로 PHP 메모리와 가비지 수집을 조정하는 것이 도움이되지 않습니다.

나 자신도 같은 문제를 겪었으므로, 3000x2000 픽셀의 50 (!) 페이지를 가진 다중 페이지 -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); 

목표는 디스크 대신 RAM에서의 픽셀 캐시를 넣어 imagick 확인하는 것입니다. 기본 위치는 files/tmp/magick-XXnnnnn 인 것처럼 보이므로/tmp가 shmfs/ramdisk에 없거나 imagick이 사용하는 임시 디렉토리를 변경하십시오.

기타 조사 제한은 imagick::RESOURCETYPE_DISK, imagick::RESOURCETYPE_FILEimagick::RESOURCETYPE_AREA입니다. 이들은 imagick::getResourceLimit() manual page에 설명되어 있습니다 (setResourceLimit() 페이지에는별로 좋지 않습니다).

내 이미지 처리 루프에는 스크립트가이 거대한 (압축을 풀 때) 이미지를 처리하기 위해 나이가 필요하기 때문에 set_time_limit(300)이 있습니다.


편집 : 최신 버전의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); 
+0

나는 이미이 문제를 포기했다. 그러나이 솔루션은 훌륭하게 작동합니다. 감사합니다 – Slemgrim

+0

누구든지 Java와 비슷한 것을 알고 있습니까? – krakover

+0

그러면 RAM 대신 디스크를 채우게 될까요? 이 캐시 란 무엇입니까? –

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

흠 잘 작동하지만 PHP 내에서 셸 명령을 호출하는 것의 추함을 제외하면 일부 프로덕션 서버에서는 보안상의 이유로 exec가 실제로 비활성화되어 있습니다. – Toumal

3

나는이 오래 알고 있지만 나는 다 퉜다 동일한 문제가 발생하여 $im->destroy() 대신 $im->clear()을 호출하면 나를 위해 메모리 누수가 해결되었습니다.

documentationImagick::destroy() has been deprecated in favor of Imagick::clear()에 따르면. 따라서 clear()을 사용해야합니다.