Repository navigation
Very bad ImageMagick resizing performance with PHP 7.1 and newer in Docker #1100
Description
After updating (from non-Docker PHP 5) to PHP 7.4 in Docker, I was experiencing performance problems with resizing images using ImageMagick. (Details: https://serverfault.com/q/1045274/31887.) After some trial-and-error, it seems that some ImageMagick performance issue is present starting in PHP 7.1 when using the Docker image.
Test script & environment
To investigate the issue, I’ve made the following simple script, with a ~2MB JPEG as input, which resizes the image and prints the time taken for each step:
<?php
$image_name = "imgbench.jpeg";
$image_size = 4000;
$image_quality = 50;
echo "PHP version: " . phpversion() . PHP_EOL;
$start = $step = microtime(true);
function bench($msg, $total = false) {
global $start, $step;
$prev = $total ? $start : $step;
$now = microtime(true);
echo number_format($now - $prev, 2) . " seconds - " . $msg . PHP_EOL;
$step = $now;
}
$image = new Imagick(); bench("init");
$image->readImage($image_name); bench("read");
$image->stripImage(); bench("strip");
$image->resizeImage($image_size, $image_size, Imagick::FILTER_LANCZOS, 1, true); bench("resize");
$image->setImageCompressionQuality($image_quality); bench("compress");
$image->setInterlaceScheme(Imagick::INTERLACE_JPEG); bench("interlace");
$image_blob = $image->getImageBlob(); bench("blob");
bench("TOTAL", true);I created a new AWS EC2 t3.medium instance with the Amazon Linux AMI and installed Docker using sudo yum install docker. Then, I built the following Dockerfile (using docker build -t imgbench .; with [version] substituted by some valid version):
FROM php:[version]
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
RUN install-php-extensions imagick
COPY ./ ./Finally, I ran the test script from above using docker run -it imgbench php imgbench.php.
All the files used for this test, can be found here: imgbench.zip.
Results
I obtained the following output/results:
| PHP 7.0: ~2s | PHP 7.1: ~19s | PHP 7.2: ~19s | PHP 7.3: ~19s | PHP 7.4: ~19s |
|---|---|---|---|---|
| PHP version: 7.0.33 | PHP version: 7.1.33 | PHP version: 7.2.34 | PHP version: 7.3.25 | PHP version: 7.4.13 |
| 0.00 seconds - init | 0.00 seconds - init | 0.00 seconds - init | 0.00 seconds - init | 0.00 seconds - init |
| 0.25 seconds - read | 0.21 seconds - read | 0.15 seconds - read | 0.16 seconds - read | 0.15 seconds - read |
| 0.00 seconds - strip | 0.00 seconds - strip | 0.00 seconds - strip | 0.00 seconds - strip | 0.00 seconds - strip |
| 0.94 seconds - resize | 18.10 seconds - resize | 18.07 seconds - resize | 17.99 seconds - resize | 18.37 seconds - resize |
| 0.00 seconds - compress | 0.00 seconds - compress | 0.00 seconds - compress | 0.00 seconds - compress | 0.00 seconds - compress |
| 0.00 seconds - interlace | 0.00 seconds - interlace | 0.00 seconds - interlace | 0.00 seconds - interlace | 0.00 seconds - interlace |
| 0.65 seconds - blob | 0.56 seconds - blob | 0.56 seconds - blob | 0.55 seconds - blob | 0.59 seconds - blob |
| 1.84 seconds - TOTAL | 18.87 seconds - TOTAL | 18.78 seconds - TOTAL | 18.71 seconds - TOTAL | 19.12 seconds - TOTAL |
It is clear that starting from PHP 7.1, something is wrong with the performance of the \Imagick::resizeImage() operation, since it’s approximately 10 times slower than in PHP 7.0.
Other factors
I also ran the test script on the same instance without Docker (using PHP from sudo yum -y install php70-cli php70-common php70-pecl-imagick) for PHP 7.0, 7.1, and 7.2. All versions showed similar (good) performance, indicating that the problem is not related to the PHP version itself, but rather something in the Docker image.
Also, I tried a Dockerfile without using install-php-extensions from mlocati/php-extension-installer, by installing ImageMagick manually in the Dockerfile:
RUN apt-get update \
&& apt-get install -y libmagickwand-dev \
&& pecl install imagick-3.4.4 \
&& docker-php-ext-enable imagickThis yielded similar performance as reported above (i.e., good performance on PHP 7.0, and bad performance on newer versions).
Activity
[-]Very bad ImageMagick resizing performance using PHP 7.1 or newer in Docker[/-][+]Very bad ImageMagick resizing performance using PHP 7.1 and newer in Docker[/+][-]Very bad ImageMagick resizing performance using PHP 7.1 and newer in Docker[/-][+]Very bad ImageMagick resizing performance with PHP 7.1 and newer in Docker[/+]wglambert commentedon Dec 7, 2020
#493 is similar, or the same
Do you get the same experience outside of Docker? Or with using Debian/Ubuntu packages over the compiled php that the image uses?
krzysztof-kabala commentedon Dec 8, 2020
Have you tried to use:
?
jhogervorst commentedon Dec 8, 2020
@wglambert If I understand correctly, it’s not exactly the same: #493 is about a performance problem with PHP 7.0 in Docker, while this problem does not occur with PHP 7.0, but only with later versions.
Also, that other issue seems to be caused by some Docker image/volume characteristics. It would be weird if that was the case here, since there’s such a huge difference between PHP 7.0 and later versions with this issue (while they share the same Docker host). Unless something radical changed between those PHP versions, which magnifies the Docker issue…
No — on the same EC2 instance, various PHP versions perform great outside of Docker:
I tried several PHP versions in Ubuntu/Debian using the following Dockerfile (using
ubuntu:16.04,ubuntu:18.04,ubuntu:20.04, anddebian:10as[version]):This yielded the following results:
Interestingly, the problem is not present here in PHP 7.0 and 7.2, but it starts appearing from PHP 7.3 (and in PHP 7.4). So now I have no clue where the cause of the problem is, since we’re seeing the same problem but with different versions here…
jhogervorst commentedon Dec 8, 2020
@krzysztof-kabala I did not use
opcachein my initial testing.I just tried using
opcachewith my original test setup (so using thephp:7.*base versions), for all PHP versions from 7.0 to 7.4. I ran the test script a few times, to giveopcachethe opportunity to ‘warm up’.The performance did not change notably. The big difference between PHP 7.0 and later versions was still present.
jhogervorst commentedon Dec 8, 2020
I did some more research, and created the following table (data from
php -i):php70-*php71-*php72-*php:7.0php:7.1php:7.2php:7.3php:7.4php:7.0-alpinephp:7.1-alpinephp:7.2-alpinephp:7.3-alpinephp:7.4-alpineubuntu:16.04ubuntu:18.04ubuntu:20.04debian:10The PHP version does not seem to affect the issue, since versions 7.1 and 7.2 do or do not have the performance problem in different scenarios. Similarly, the Imagick version does not seem to affect it.
However, all the scenarios with bad performance are using the same version of ImageMagick: 6.9.10-23. Maybe that points to something?
jhogervorst commentedon Dec 8, 2020
Workaround
Alright, I found a workaround: the
php:alpinepackages do not have the performance problem!They do seem slightly slower than the other performant environment, but that’s ‘just’ a ~50% increase of processing time, rather than 10 times slower (900% increase).
I’ve updated the table above to include the specific versions.
krzysztof-kabala commentedon Dec 8, 2020
"base" php image:
log:
"custom" php image (with
libjpeg62-turboinstalled + custom ImageMagic setup):log:
seems like ImageMagic issue, not a php or docker one :)
tianon commentedon Dec 9, 2020
Can confirm -- downloaded the example
imgbench.jpegand used the followingDockerfile:The output is exactly in line with the 19s reported:
However, if I replace
imagemagickwithgraphicsmagick-imagemagick-compat, the result is much faster:So this is firmly a case for a bug at https://bugs.debian.org/src:imagemagick (although possibly an upstream bug), and a potential workaround would be to try to use
libgraphicsmagick1-dev,libgraphicsmagick++1-dev, and/orgraphicsmagick-libmagick-dev-compatinstead.jhogervorst commentedon Dec 9, 2020
@tianon Thank for your efforts! I will see if I can report this to https://bugs.debian.org/src:imagemagick.
For people finding this issue: I tried @tianon’s suggestion of using alternative packages. When using
libgraphicsmagick1-devandlibgraphicsmagick++1-dev(with PHP in Docker), the performance issue remained. Withgraphicsmagick-libmagick-dev-compat, I was not able to install the PHP Imagick extension (it couldn’t find ImageMagick).So the easy workaround seems to be using
php:alpine, or installing ImageMagick from source as suggested by @krzysztof-kabala.beinbm commentedon Sep 3, 2022
If someone reaches this thead:
Performance issue is resolved in newer Imagemagick package of debian 11 (bullseye)
Docker: php:7.3-apache-buster
Debian 11 (bullseye)
Version: ImageMagick 6.9.11-60 Q16 x86_64 2021-01-25 https://imagemagick.org/
PHP version: 7.3.33
0.00 seconds - init
0.17 seconds - read
0.00 seconds - strip
1.16 seconds - resize
0.00 seconds - compress
0.00 seconds - interlace
0.30 seconds - blob
1.63 seconds - TOTAL
Docker: php:7.3-apache-buster
Debian 10 (buster)
Version: ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org/
PHP version: 7.3.33
0.00 seconds - init
0.15 seconds - read
0.00 seconds - strip
26.97 seconds - resize
0.00 seconds - compress
0.00 seconds - interlace
0.57 seconds - blob
27.69 seconds - TOTAL
For us the easiest fix of the performance problem was to upgrade debian :)