5

There are two methods in Imagick: clear() and destroy().

But I'm not sure when to use them.

For example, do I have to destroy() even after overwriting the only reference I have?

$img = new Imagick($path1);
// do something with $img, then load a different image
$img = new Imagick($path2); // should I have destroyed $img before doing this?

Does Imagick release the resources if I overwrite the reference?

If not, this is both annoying and scary.

ChocoDeveloper
  • 14,160
  • 26
  • 79
  • 117
  • I would imagine that it is flagged for garbage collection when all references are lost. – crush Jan 22 '13 at 16:54
  • @crush Yes but why do these methods even exist? Why not free the resources with '$img = null', like with PDO? I'm thinking maybe Imagick keeps the resources in memory in case you use them again. It lacks documentation. – ChocoDeveloper Jan 22 '13 at 16:57
  • I guess if you wanted to create an image, output it, then start creating another image (without using the new operator), all with the same object. It would use less memory because you don't have to wait for garbage collection. – crush Jan 22 '13 at 17:05
  • `$img = null` won't free the resources if there still are other references to the image object. With `destroy` you can force the destruction. – nwellnhof Mar 28 '13 at 20:53

2 Answers2

4

I did a quick and dirty test, image1 is 85kb image2 is 457kb

$start = microtime();

for($i=0; $i<10; $i++){
    $img = new Imagick('./image1.jpg');
    $img->setImageResolution(72,72);
    $img->resampleImage(72,72,imagick::FILTER_UNDEFINED,0);
    $img->destroy();

    $img = new Imagick('./image2.jpg');
    $img->setImageResolution(72,72);
    $img->resampleImage(72,72,imagick::FILTER_UNDEFINED,0);
    $img->destroy();
}

$end = microtime();
$len = $end - $start;
echo number_format($len, 2),'<br /> <br />';

function kb($n){
    return ceil($n/1024);
}

echo 'memory usage - ',kb(memory_get_usage()),' / ',kb(memory_get_peak_usage()),' <br />';

And then I commented out the destroy lines, and ran it again. strangely it seemed to use more memory when using destroy() but only 3 or 4 k. the timer didn't show much different, and when I ran a basic apache bench load test

ab -n 20 -c 5 http://ubunty.local/sandbox/stackexchange/imagick.php

There didn't seem to be much in it.

I was expecting destroy to use less memory. even using image2 in a different variable didn't seem to make a difference

$img2 = new Imagick('./image2.jpg');

If there is a reason to use ->destroy() then it must be down to something I forgot to measure, as far as I can see.

CodeMonkey
  • 3,271
  • 25
  • 50
  • It might be because of this - http://stackoverflow.com/questions/9993085/php-imagick-memory-leak – aandis Jun 23 '15 at 11:04
  • NOTE: ".destroy()" has been deprecated in favor of ".clear()". I am not changing the original answer, because it's also in relationship to resource use, and I have not replicated the tests. – Robert Mauro Aug 05 '20 at 16:30
3

Yes.

Note that clear() is preferred over destroy() according to the docs.

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

You can also run a cron to delete the temp files for you, otherwise your server could crash. This is not php code, it is command line code.

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

# cron
45 * * * * find /tmp/ -name "magick-*" -type f -delete
kintsukuroi
  • 1,332
  • 16
  • 15