2012-04-03 64 views
6

Tôi phải render một thứ gì đó bằng Imagick trên PHP CLI. Tôi nhận thấy rằng mỗi 3-5 ngày bộ nhớ máy chủ được đầy đủ, vì vậy tôi thậm chí không thể connet qua ssh hoặc ftp.Rò rỉ bộ nhớ PHP Imagick

với memory_get_usage() tôi đã thu hẹp rò rỉ bộ nhớ xuống phần tưởng tượng của tập lệnh. kịch bản trông giống như sau:

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

tôi phá hủy các tài liệu tham khảo hình ảnh, và unset các imagick và đối tượng imagickDraw, nhưng kịch bản sẽ không phát hành bất kỳ bộ nhớ. Phương thức setFillColor() chiếm nhiều bộ nhớ nhất

Tôi có thể làm gì khác để giải phóng dung lượng được sử dụng bởi imageick không?

image of the memory consumption

Trả lời

15

imagick sử dụng thư viện được chia sẻ và việc sử dụng bộ nhớ của nó nằm ngoài tầm với của PHP, do đó việc điều chỉnh bộ nhớ PHP và bộ sưu tập rác sẽ không giúp ích gì.

Tôi cũng có cùng một vấn đề, cố gắng xử lý hình ảnh nhiều trang-tiff với 50 (!) Trang 3000x2000 pixel. Giải pháp là để có trí tưởng tượng đặt bộ nhớ cache pixel của nó trên đĩa.

thêm này trước khi tạo các đối tượng Imagick giải quyết vấn đề đối với tôi:

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

Mục đích là để làm cho imagick đặt bộ nhớ cache điểm ảnh của nó trên đĩa thay vì trong RAM. Vị trí mặc định có vẻ là tệp/tmp/magick-XXnnnnn, vì vậy hãy đảm bảo/tmp không có trên shmfs/ramdisk hoặc thay đổi thư mục tạm thời mà imagick sử dụng.

Giới hạn resouce khác để điều tra: imagick::RESOURCETYPE_DISK, imagick::RESOURCETYPE_FILEimagick::RESOURCETYPE_AREA. Chúng được mô tả trong các imagick::getResourceLimit() manual page (không quá tốt trong trang cho setResourceLimit()).

Trong vòng xử lý hình ảnh của tôi, tôi có set_time_limit(300), vì tập lệnh mất nhiều thời gian để xử lý hình ảnh khổng lồ này (khi giải nén).


EDIT: Trong các phiên bản gần đây, setResourceLimit() không nên được gọi như một phương pháp tĩnh, nhưng trên đối tượng thực tế thay vào đó, chẳng hạn như:

$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

tôi đã từ bỏ vấn đề này. nhưng giải pháp này hoạt động tốt. cảm ơn – Slemgrim

+0

Bất cứ ai cũng biết bất cứ điều gì tương tự trong Java? – krakover

+0

Vì vậy, nó sẽ điền vào đĩa thay vì RAM? Bộ nhớ cache này là gì? –

1

Xdebug đã không thể giúp tôi .. vì vậy tôi đã quyết định làm tìm cho ra một giải pháp khác. tôi đã đưa ra với việc sử dụng hình ảnh ma thuật trực tiếp:

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

giải pháp này hoạt động theo cách mượt mà thì imagick một. nhưng tôi không thích mã dễ bị lỗi.

+0

Hmm cũng chắc chắn nó hoạt động, nhưng ngoài sự xấu xí của gọi lệnh shell từ bên trong php, trên một số máy chủ sản xuất exec thực sự vô hiệu hóa vì lý do bảo mật. – Toumal

3

Tôi biết điều này là cũ nhưng tôi chạy vào cùng một vấn đề và gọi số $im->clear() thay vì $im->destroy() cố định rò rỉ bộ nhớ cho tôi.

Theo số documentationImagick::destroy() has been deprecated in favor of Imagick::clear(). Vì vậy, clear() nên được sử dụng.