Я обновляю часть системы с PHP 5.5 (установленной непосредственно на AWS EC2) до PHP 7.4 в Docker (работающей на AWS EC2 с использованием Docker Compose). Производительность изменения размера изображения с использованием ImageMagick значительно снизилась.
Тестовый сценарий
Чтобы диагностировать проблему, я создал следующий простой скрипт, используя в качестве входных данных JPEG-файл размером 5 МБ:
<?php
$image_name = "imgbench.jpeg";
$image_size = 4000;
$image_quality = 50;
$image = new Imagick();
$image->readImage($image_name);
$image->stripImage();
$image->resizeImage($image_size, $image_size, Imagick::FILTER_LANCZOS, 1, true);
$image->setImageCompressionQuality($image_quality);
$image->setInterlaceScheme(Imagick::INTERLACE_JPEG);
$image_blob = $image->getImageBlob();
Измерения
Из моих измерений следует, что вызовы resizeImage()
и getImageBlob()
занимают большую часть времени выполнения, как и ожидалось. Я запустил этот скрипт 5 раз на старой и новой системе (через nginx с php-fpm) и обнаружил следующее среднее время выполнения:
- Старая система (PHP 5.5): в среднем 2,5 секунды
- Новая система (PHP 7.4 в Docker): в среднем 14,8 секунд
Другими словами, настройка PHP 7.4 — этов 6 раз медленнеечем старая настройка PHP 5.5! (Время измерялось из скрипта PHP, поэтому nginx/php-fpm не должен был играть никакой роли.)
Для других типов запросов новая настройка работает нормально (немного быстрее старой, как и можно было ожидать от PHP 7). Обе системы используют один и тот же тип экземпляров EC2, и для контейнера Docker в новой системе не установлены явные ограничения ресурсов. Поэтому я бы не ожидал, что это изменение размера будет медленнее, чем раньше.
Есть ли у кого-нибудь идеи, что может быть причиной этого, и, что еще важнее, как можно улучшить производительность новой системы?
Использование системы
Старая система использовалась во время выполнения тестового скрипта, но у нее было достаточно процессорного времени/памяти. Во время выполнения тестового скрипта загрузка процессора достигла >300% (согласно top
).
Новая система не использовалась во время выполнения тестового скрипта, поэтому у нее также было достаточно ресурсов ЦП/памяти. Однако здесь загрузка ЦП достигла только 150–180%, согласно top
и docker stats
.
Настраивать
Старая система
На старой системе (использующей x64 Amazon Linux AMI версии 1) PHP был настроен следующим образом:
sudo yum install php55-pecl-imagick ...
И он показывает следующую информацию:
$ php -i
phpinfo()
PHP Version => 5.5.38
(...)
imagick
imagick module => enabled
imagick module version => 3.4.4
imagick classes => Imagick, ImagickDraw, ImagickPixel, ImagickPixelIterator
Imagick compiled with ImageMagick version => ImageMagick 6.7.8-9 2016-06-22 Q16 http://www.imagemagick.org
Imagick using ImageMagick library version => ImageMagick 6.7.8-9 2016-06-22 Q16 http://www.imagemagick.org
Новая система
Новая система использует Docker ( sudo yum install docker
на x64 Amazon Linux 2) со следующим Dockerfile для контейнера PHP:
FROM php:7.4-fpm
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
RUN install-php-extensions imagick
(Та же проблема с производительностью возникала при установке расширения PHP imagick
и libmagickwand-dev
вручную, без mlocati/php-extension-installer
.)
Это дает следующую информацию:
$ docker-compose exec php php -i
phpinfo()
PHP Version => 7.4.13
(...)
imagick
imagick module => enabled
imagick module version => 3.4.4
imagick classes => Imagick, ImagickDraw, ImagickPixel, ImagickPixelIterator, ImagickKernel
Imagick compiled with ImageMagick version => ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
Imagick using ImageMagick library version => ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
решение1
Мне удалось обойти эту проблему, используя php:alpine
вместо этого изображения.
Точная причина пока не ясна, более подробную информацию см. в следующей статье:https://github.com/docker-library/php/issues/1100