Бенчмарк графических библиотек для PHP

    image
    В проекте который мы сейчас разрабатываем много работы с фотографиями, в результате чего скорость графической библиотеки является фактически главным фактором при оптимизации сайта. Не секрет что ImageMagick давно стал стандартом разработки на PHP, хотя уже некоторое время его оттуда сталкивает форк под названием GraphicsMagick. Мне стало интересно насколько сильно они отличаются и сколько форы могут дать старому доброму GD. К счастью как раз недавно вышел графический модуль для PHPixie который поддерживает все три библиотеки, что и позволило мне провести достаточно интересные тесты.


    В духе самого фреймворка экспериментировать будем на фее которая справа ( взята с девиантарта http://j-scott-campbell.deviantart.com/ ). Если кому-то покажется что в ней слишком много иннуендо, то посмею напомнить что уже больше 20 лет стандартным рисунком тестирования графических алгоритмов является Lenna из плейбоя.

    Сейчас следует короткое описание тестов и выходные рисунки. В конце статьи будет сам бенчмарк скорости работы одной таблицей.

    Простое масштабирование

    Итак сначала попробуем уменьшить ее до 100 пикселей по ширине.
    $pixie->image->read($dir.'fairy.jpg')
    			->resize(200)
    			->save($dir.'resize.jpg');
    


    image

    Разницы особой на первый взгляд незаметно, но например ее глаз на GD версии не имеет того ярко выраженного зеленого цвета как у Imagick и Gmagick.

    Создание квадратной аватарки

    Чтобы сделать автарку квадратной ее нужно сначала масштабировать по меньшей стороне а затем обрезать по большей. На PHPixie это делается довольно просто:

    $pixie->image->read($dir.'fairy.jpg')
    			->resize(200, 200, false)
    			->crop(200, 200)
    			->save($dir.'crop.jpg');
    

    image
    Очевидно что выглядеть они будут идентически предидущим.

    Написание текста и создание пустого изображения

    Теперь попробуем создать белый рисунок и написать текст фиолетовым цветом используя TTF шрифт.

    $pixie->image->create(300, 70, 0xffffff, 1)
    			->text("Hello World", 50, $dir.'/Sofia-Regular.ttf', 10, 50, 0x5B43AA)
    			->save($dir.'text.jpg');
    


    image

    Тут результаты немного подраматичней. GD почему-то сделала цвет текста темней и гораздо хуже сработал антиалиасинг, в результате чего края текста немного размыты. У обеих Magick-ов текст получился гораздо лучше.

    Разбиение текста на строки

    Текст на строки разбивает сама PHPixie, но для этого она использует информацию о метрике текста от графической библиотеки. Так как приходится считать размер каждого слова это может быть довольно дорогим процессом. Итак попробуем поместить на пустую страницу кусочек песенки.
    
    $text = "When I closed my eyes to the shimmering light ".
               "all memory faded and I could see ".
               "that a mushroom circle of red and white ".
               "and myriad fairies surrounded me. ";
    
    $pixie->image->create(300, 180, 0xffffff, 1)
    			->text($text, 20, $dir.'/Sofia-Regular.ttf', 10, 50, 0x5B43AA, 1, 300)
    			->save($dir.'wrap.jpg');
    


    image

    На меньшем шрифте недостатки не так заметны но если присмотреться к изгибам то довольно легко можно отличить. Но надо заметить что Imagick потратил намного больше времени, прежде всего из за пересчитывания метрики шрифта на каждом слове (ведь приходится наново считывать шрифт с диска каждый раз) в то время как GD и Gmagick были намного быстрее.

    Наложение и оборачивание рисунков

    Этот тест наиболее оторван от реальности, но хотелось побенчить скорость наложения рисунков и вообще операции посложнее. Итак мы создаем пустой рисунок, с одной стороны ставим автарку феи а с другой ту же аватарку только обернутую по горизонтали и вертикали да еще и развернутую боком.

    
    $canvas = $pixie->image->create(400, 200);
    	$fairy = $pixie->image->read($dir.'fairy.jpg')
    				->resize(200, 200, false)
    				->crop(200, 200);
    	$canvas	->overlay($fairy, 0, 0)
    			->overlay($fairy->flip(true, true)->rotate(90), 200, 0)
    			->save($dir.'overlay.jpg');
    


    image

    Скорость работы


    А вот и сам бенчмарк. По горизонтали слева-направо проведенные тесты, по вертикали среднее время исполнения ( каждый тест прогонялся 100 раз).

    image

    Вывод, лучше всего таки использовать Gmagick, если его нет то Imagick. Над GD можно задуматься только в случае если надо будет писать много текста и то не очень замысловатым шрифтом.

    Кстати отдельно замечу насколько сильно мне понравился интерфейс самой PHPixie в этом плане, в особенности наличие функций для множества стандартных действий (тот же самый враппинг текста) для которых раньше приходилось качать отдельные классы.
    Поделиться публикацией

    Похожие публикации

    Комментарии 41

      +11
      что ж вы замеры потребления памяти не сделали? у GD очень большие аппетиты при обработке больших изображений, порой настолько, что пользоваться им нет возможности. Так что скорость выполнения — это хорошо, но еще есть и памяти и умение не выбрасывать ошибку, если память кончается, а продолжать работать, складывая результаты в файл, как умеет imagick.
        +1
        Ещё стоило сравнить размеры получаемых файлов.
          +1
          Хм ну в нашем случае памяти не так жалко. Так как память не такая уж дорогая, и 4 Гб которые есть у сервера не были проблемой ни в одном случае. GD действительно самый прожорливый. Насчет сравнивания размера файлов то здесь больше зависит от степени сжатия (если говорить о JPEG) а не от самой библиотеки, так как алгоритм повсюду похож.
            0
            Вы упускаете из виду тот момент, что вы тестировали только на себе. Если это будет частью какого-то сервиса и пользоваться этим будут много людей сразу, то любовь библиотек к процессору и памяти не менее важна, чем быстродействие. Я сам недавно напоролся: применил PHPExcel для обработки, сам протестировал — нормально, всё очень быстро работает. А вот как люди пользоваться начали, 5-10 одновременных обращений к PHPExcel заставляли сервер так задуматься, что иногда в течение 5 минут все остальные обратившиеся получали таймаут.
          0
          >Очевидно что выглядеть они будут идентически предидущим.
          Если придираться, то ГД сильнее крыло обрезал снизу.

          >GD почему-то сделала цвет текста темней и гораздо хуже сработал антиалиасинг
          по-моему три одинаковые картинки О_О
            +3
            По-моему, не хватает «диффа» картинок для объективного сравнения.
              0
              Разницу видно меньше потому-что картинки немного пережал сам сервер (imgur) на который я аплоудил. Но код есть в статье так-что можете попробовать сгенерить их сами =)
                0
                Это всё ваш jpeg. Png+habrastorage решает эти проблемы.
                  0
                  Каюсь. Не прав.
              0
              Нужно смотреть на мелкие детали. Например на нитки под попой феи) Там явно видна разница между GD и остальными.
              +2
              У кого ест много памяти, попробуйте php 5.5. В моем случае (конвертация с предобработками из svg) потребление памяти снизилось с 8.8 МБ (php 5.3) до 3.5 МБ (php 5.5). Imagick, memory_get_peak_info()
                +1
                Есть еще imagine. Куча функций, поддерживает те же либы. Правда у меня последний раз, когда я ее использовал писанина текстом на картинке не заработала (для GD).
                  0
                  она хороша, особенно нравятся еффекты =)
                  Если бы в пиксе не было бы своей библиотеки то использовали бы имеджин.
                    0
                    Что за библиотека можно поподробней?
                      0
                      В статье есть линк. Фреймворк phpixie.com
                        +1
                        Извиняюсь, я думал это просто аналог imagine, название какое-то картиношное.
                  +5
                  Сравнение сделано из рук вон плохо. Вы сохранили картинки в jpg с параметрами по-умолчанию и ни слова не сказав ни о размере картинки, ни о времени сжатия, принялись сравнивать качество. И так известно, что jpeg можно сохранить с разным качеством. И так известно, что у разных библиотек настройки по-умолчанию разные. Нужно подбирать параметры так, чтобы размер получился примерно одинаковый, и тогда смотреть качество и скорость.

                  Потом, какой алгоритм интерполяции вы использовали для изменения размеров? Качество и время работы в первую очередь зависит именно от него, от выбора библиотеки во вторую. Сравнивать библиотеки нужно было на одном алгоритме.

                  Не зачет.
                    0
                    Посмотрел в пиксю, по дефолту для JPEG качество 95% стоит
                      0
                      Во-первых, не 95, а 90.

                      Во-вторых 90 чего? Нет единой шкалы качества jpeg, у каждой библиотеки она разная (в фотошопе вообще от 1 до 12, например). Единственное мирило — сравнение качества при примерно одинаковом размере.
                        0
                        Не спорю но мы тут сравниваем не так качество как скорость работы. Я понимаю что мог бы лучше подогнать параметры, но результат не так уж и изменился б.

                        Спасибо что поправили с 95, я что-то недосмотрел
                          +1
                          > не так качество как скорость работы
                          А я вот увидел, что вы именно качество сравниваете, причем по результату сжатия jpeg сравниваете качества рендеринга шрифтов, что вообще бред. Вы можете убрать это из топика.
                        0
                        В Imagemagick i Gmagick алгоритм LANCZOS, в GD тоже. Но в любом случае бенчмарк показывает то что главное: скорость и Gmagick явно впереди.
                          0
                          > В Imagemagick i Gmagick алгоритм LANCZOS, в GD тоже.

                          В GD далеко не LANCZOS, потому что даже не свертки. Тут все написано: habrahabr.ru/post/243285/
                      +2
                      никогда раньше не обращал внимания на Gmagick, оказалось занятная вещь, упор на скорость — обгоняет imagick во всём на многоядерных системах заметно лучше (тесты) + имеет вместо нескольких команд (convert, mogrify) один бинарник gm, которому можно задавать команду, например gm convert. Буду пробовать в следующем проекте.
                        0
                        > имеет вместо нескольких команд (convert, mogrify) о

                        ну так они же для разного )
                          0
                          вы не поняли, можно делать так gm convert, gm mogrify, mogrify montage, т.е. те же команды, только внутри одного бинарника. Я считаю, что удобнее использовать — скомандовал gm и сразу видишь список команд.
                          0
                          Написание текста

                          Не очень показательный пример, надо было сравнить вывод текста маленького размера — gd его мягко говоря хреново выводит («багу» хз сколько лет, при желании можно даже найти интересный патч)

                            0
                            Какие опции использовались в ImageMagick для создания превьюшек?
                            В ImageMagick есть очень большой диапазон возможностей создавать превьюшки, которые очень сильно влияют как на выходной размер файла так и на скорость выполнения. Например по скорости работы сильно отличается адаптивный ресайз vs обычный ресайз.

                            Каким образом был собран Imagick?
                            Указали ли при сборке возможность для работы в несколько потоков?

                            Насколько я понял тест проводился при создании одной превьюшки в одно и тоже время?
                            В проекте не предполагается ситуации когда в один и тот же момент будет создаваться несколько превьюшек?
                              0
                              ресайз LANCZOS, при компиляции оставлял все по дефолту. А вот насчет возможности работы в несколько потоков то при чем тут? ведь Imagick для пхп и так только по одному обрабатывает. Если я бы генерил много превюшек нараз то делал бы не через ПХП а напрямую используя mogrify.
                              0
                              Спасибо за сравнение, но у PHPixie настолько неудачный маскот, что ей, мне кажется, ничего не поможет.
                                0
                                ну вы ж не на маскоте пишете ) зато оригинально)))
                                0
                                Почему по коду идет сохранение в JPEG, а сами картинки выложены в PNG?
                                  +1
                                  Чтобы слить все картинки в одну, PNG lossless формат так что своих недостатков не вносит
                                  0
                                  В простом масштабировании у вас у GD размер картинки по вертикали на 1 пиксель больше. Отсюда и разница на глазе. Между Imagick и Gmagick разницы практически нет вообще (единицы пикселей на все изображение). Разницу лучше всего смотреть в фотошопе через режимы наложения (разница и деление).

                                  В написании текста и создании пустого изображения у вас разное качество сжатия jpg, это же очевидно под лупой в фотошопе. Видимо в GD дефолтное качество стоит ниже всех остальных, а в Gmagick — самое высокое.

                                  В статье не сказано как проводились тесты скорости, а глядя на куски кода — подозреваю что измерялось время исполнения всего скрипта. Очевидно что ресайз изображения это: распаковка графического формата (jpg скорее всего), сам ресайз, упаковка в формат (png/jpg). Хотелось бы видеть тесты времени только ресайза.

                                  Алсо немаловажно я считаю провести тест на чтение формата/сохранение в формате для основных популярных форматов: jpg/png/gif

                                  upd. так же ни слова не сказано о алгоритме интерполяции при ресайзе. Есть ведь линейная, бикубическая, а так же куча их модификаций.
                                    –1
                                    В комментах уже упомянул что там LACZOS. Насчет шрифтов в ГД то вы не правы. Во первых эти шрифты так же выглядят и в PNG, во-вторых (тоже с комментов) сам фреймворк ставит для джпега по дефолту качество 90%
                                      0
                                      Мне кажется нужен апдейт поста в духе:
                                      Вот шрифты, делал <спойлер «так и так»>пхп код</спойлер>, картинки получил вот такие и такие <картинка GD.png> <картинка Imagick.png> <картинка Gmagick.png>
                                      Замеры скорости делал <спойлер «так и так»>пхп код</спойлер>, результаты ниже.

                                      Потому что судя по первому бенчмарку — допускаю еще «ляпов». Вы сейчас утверждаете, что качество сжатия одинаковое, и шрифты так же выглядят в PNG, а вы сохраните в PNG и продемонстрируйте, ибо сейчас я вижу что у GD
                                      больше артефактов от сжатия в jpg

                                      Причем значительно больше, ибо вокруг стали появляться желтые пиксели
                                        –1
                                        Вот GD в формате PNG i.imgur.com/m1n5zh7.png
                                        Как по мне то идентично
                                          +1
                                          Этот PNG отличается от того GD JPG-а. Прежде всего шириной надписи, при попиксельном наложении видно что надпись на пару пикселей уже. Кроме того вы опять таки не привели код, которым была нарисована эта надпись. Как тут можно вообще говорить о том, что GD неправильно рисует текст и делает цвет темнее? Если вы делаете бенчмарк — то надо быть точным
                                            –1
                                            Тот же код что и в статье, только поменялся путь сохранения
                                              +1
                                              Кстати я взял пипеткой цвет из PNG от GD. Он оказался в точности 0x5B43AA, а вот попытка взять цвет от Gmagick и Imagick дает примерно 0x5b43a9, но опять же, о каком взятии цвета может идти речь, когда там jpg я не знаю
                                    0
                                    Стандарт — это всё-таки GD. Кстати, померьте ещё imlib2, если сможете скомпилировать под новые версии PHP, она на масштабировании раньше делала всех.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое