簡體   English   中英

PHP Imagick 內存泄漏

[英]PHP Imagick memory leak

我必須在 PHP CLI 上用 Imagick 渲染一些東西。 我注意到每 3-5 天服務器內存就會變滿,所以我什至無法通過 ssh 或 ftp 連接。

使用 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 使用的空間嗎?

內存消耗的圖像

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() 手冊頁中有描述(在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);

我知道這是舊的,但我遇到了同樣的問題,調用$im->clear()而不是$im->destroy()為我修復了內存泄漏。

根據文檔Imagick::destroy() has been deprecated in favor of Imagick::clear() 所以應該使用clear()

你可以用這個。

請注意,根據釋放內存使用的文檔, 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

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 更順暢。 但我不喜歡容易出錯的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM