Двойная скорость и половина памяти: оптимизация PHP 7

в 13:10, , рубрики: intel xeon, php, PHP 7, Блог компании Intel, высокая производительность, оптимизация, производительность, разработка, Разработка веб-сайтов

Ключ к высокой производительности приложений – оптимизация. При этом, чем ниже уровень, на котором код подстраивают под особенности аппаратного обеспечения – тем большего можно добиться. А ещё более впечатляющих результатов можно достичь тогда, когда при проектировании аппаратного обеспечения учитываются особенности кода. Сегодня мы расскажем о том, как идёт работа над ускорением PHP 7, которую совместно, практически непрерывно, ведут Intel и сообщество PHP-разработчиков.

Двойная скорость и половина памяти: оптимизация PHP 7 - 1

Один из аспектов этой работы заключается в том, что Intel делится знаниями о своих технологиях, а разработчики внедряют новые возможности в ядро PHP, совершенствуют код. Производительность свежих сборок тестируют, на основе испытаний делают выводы, ищут пути решения проблем.

Например, на сайте Languages Performance можно наблюдать за динамикой производительности PHP, полученной на основе ежедневно обновляемых показателей. Здесь же есть сведения и о других платформах. Среди них – Python, Node.js, HHVM.

Если говорить о PHP, то вышеупомянутые усилия привели к тому, что PHP 7, в сравнении с PHP 5, демонстрирует практически двукратный рост производительности на серверах с процессорами Intel Xeon. При этом значительно уменьшена потребность PHP в памяти. Это очень важное достижение для интерпретируемого языка, который используется в проектах с очень высокими нагрузками. Обратите внимание на то, что речь здесь идёт о результатах, которых можно добиться на реальных проектах. Кроме того, производительность PHP 7 показывает рост с каждым новым поколением архитектуры Intel (IA), которое вводит новые возможности, улучшающие аппаратную эффективность выполнения кода.

Улучшенное управление памятью и более быстрое исполнение

Один из основных факторов, влияющих на производительность приложений – это то, как они работают с памятью.

У современных микропроцессоров есть несколько уровней кэш-памяти, для кода и данных, и каждое новое поколение процессоров Intel Xeon отличается от предыдущего увеличенным размером кэша. Однако, кэш не перестаёт быть ценнейшим ресурсом, его объём, по сравнению с устанавливаемой в современные системы оперативной памятью, всё ещё очень мал. В то же время, основное занятие классических интерпретаторов, таких, как PHP, сводится к интенсивной работе с памятью, к копированию и перемещению больших объёмов данных.

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

Большая часть работы, которую проделала Intel для улучшения скорости работы PHP, направлена на повышение эффективности работы с памятью.

Уменьшение потребления памяти на 50%

Первое важнейшее улучшение в PHP 7 – это уменьшенное потребление памяти. Пользуясь результатами исследований Intel, а также собственным обширным опытом, сообщество PHP серьёзно уменьшило структуры данных в PHP 7. В частности, zVal уменьшили на 33%, структуру данных bucket (часть хэш-таблицы), так же сократили на 33%, оптимизировали менеджер памяти, что привело к увеличению эффективности работы с памятью на 75%. Общая потребность в памяти PHP 7 была уменьшена примерно на 50% в сравнении с PHP 5. Только это дало, например, 30%-е улучшение производительности WordPress-проектов, использующих сервера с процессорами Intel.

О производительности PHP 7

Для исследования производительности PHP и поиска возможностей по оптимизации, Intel использует эталонные рабочие нагрузки и тесты Zend. После того, как благодаря подобным испытаниям обнаруживаются узкие места, Intel передаёт сведения сообществу, предоставляя рекомендации, касающиеся того, как ускорить наиболее важные модули системы. Сообщество же оптимизирует код. Как результат, удалось добиться роста производительности PHP 7 примерно в два раза.

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

Во-первых, при оптимизации и тестировании использовались рабочие нагрузки, максимально близкие к тем, которые создают реальные приложения. Продемонстрированный рост производительности получен не после исполнения синтетических тестов, а после испытаний на реальных приложениях, таких, как WordPress, Drupal, MediaWiki. Например, WordPress работает, в среднем, вдвое быстрее на PHP 7, запущенном на сервере с процессором Intel, нежели PHP 5. Испытания проводились и с использованием узкоспециализированных тестов, нацеленных на исследование архитектуры Intel.

Во-вторых, улучшения PHP 7 касаются всех приложений. Переход на PHP 7 не требует дополнительных усилий по оптимизации приложений для работы на процессорах с архитектурой Intel. Другими словами, при исследовании производительности применялись стандартные тесты, которые не были специально оптимизированы для исследования производительности PHP 7. После обновления PHP до седьмой версии на серверах, оснащённых процессорами Intel Xeon, можно сразу же увидеть рост производительности приложений.

Рекомендации по дальнейшему улучшению производительности PHP

Переход на PHP 7, если не принимать в расчёт другие факторы, даёт улучшение производительности, но есть две вещи, которые позволят повысить производительность ещё больше.

  • Первая заключается в использовании серверов, построенных на процессорах Intel Xeon.
  • Вторая – в сборке PHP с использованием профильной оптимизации (Profile-Guided Optimization, PGO).

Intel Xeon и увеличение производительности

Intel вкладывает значительные силы в оптимизацию как аппаратного, так и программного обеспечения. Каждое новое поколение микроархитектуры Intel содержит улучшения, которые увеличивают и эффективность работы аппаратных компонентов, и производительность ПО. Простой переход на новое поколение процессоров способен дать значительный, порой очень серьёзный, рост производительности. Кроме того, Intel изучает и оптимизирует программное обеспечение для того, чтобы гарантировать то, что приложения смогут быстро выполняться на IA-процессорах, полноценно используя доступные аппаратные возможности.

Одним из основных условий улучшения производительности PHP были обширные исследования Intel, посвященные тому, как программы, написанные на динамических и интерпретируемых языках программирования, работают на IA. Основываясь на тщательном анализе, Intel провела низкоуровневую оптимизацию процессоров Intel Xeon для того, чтобы они могли лучше обрабатывать интерпретаторы, такие, как PHP, HHVM, Python и Node.js.

Для ещё большего повышения производительности, Intel и сообщество PHP оптимизировали ядро PHP для того, чтобы воспользоваться улучшениями микроархитектуры, которые были представлены в новом поколении процессоров Intel.

Когда появляются новые аппаратные возможности, Intel выявляет специфические области в PHP, которые можно оптимизировать. Подобные оптимизации, например, касающиеся библиотеки libc, приводят к росту производительности для широкого спектра приложений.

Вот сводная таблица по основным улучшениям, которые помогают повысить производительность PHP.

Аппаратная оптимизация Описание Преимущества для производительности
Улучшенное управление памятью Увеличенные размеры кэшей и буферов ассоциативной трансляции (TLB), более быстрые обработчики кодов операций. Помогает уменьшить воздействие на производительность большой потребности PHP в памяти. Хотя потребность в памяти у PHP 7 меньше, чем у предыдущих версий, она всё ещё значительна. Улучшенное управление памятью помогает уменьшить влияние потребностей PHP на производительность.
Более совершенные алгоритмы, позволяющие уменьшить ошибки предсказания ветвлений Использование более совершенных алгоритмов помогает уменьшить ограничения, возникающие на входе в конвейер процессора для случаев, когда нужной инструкции нет в кэше, или при неправильных предсказаниях ветвления. В результате уменьшается число потерянных циклов процессора при упреждающем выполнении кода. Для всех интерпретируемых языков программирования характерны большие задержки на входе в конвейер. Новые алгоритмы позволяют более эффективно исполнять PHP-программы и другой интерпретируемый код.
Наборы инструкций Intel Advanced Vector Extensions 2 (AVX2) и Intel Streaming SIMD Extensions (SSE) Новый набор 256-битных инструкций в процессорах Intel Xeon. Когда переходят на использование SSE/SSE4 или AVX-реализации API libc, таких, как memcpy(), memset() и memcmp(), возрастает производительность операций PHP, которые подразумевают выполнение операций с памятью. Эти SIMD-инструкции способны улучшить производительность. Например, компиляция HHVM с включением AVX2, позволяет добиться немедленного прироста производительности на 5% при многопоточном исполнении WordPress.
Ручная оптимизация низкоуровневого кода. Ассемблерный код ответственных модулей, например, memset() и memcpy() в HHVM, оптимизирован вручную. Похожие улучшения выполнены так же для PHP 7, Python (и в v2.7 и в v3.5), и для других платформ. Переписав вручную код на ассемблере в HHVM, Intel обнаружила значительный рост производительности на серверах. Вот пример лишь одной оптимизации в интерпретаторе PHP: патч Intel к функции fast_memcpy(). Оптимизация расширила эту функцию некоторыми специализированными инструкциями из Intel SSE2. Подобный подход помогает интерпретируемым языкам лучше и быстрее работать, полноценно пользоваться аппаратными возможностями, такими, как большие размеры кэша третьего уровня (Last Level Cache, LLC).

▍Увеличенные размеры кэшей и некэшируемая запись

Выбор подходящей платформы, в данном случае речь идёт о сервере на базе Intel Xeon, это весьма важно для обеспечения высокой производительности PHP-решений. Это так потому что самые современные сервера от Intel, на Xeon v3 и v4, лучше используют кэш-память большого размера. Эффективность и скорость исполнения кода так же выигрывают от активной работы Intel по постоянному совершенствованию библиотеки libc и других компонентов для улучшения производительности PHP. В эту работу входит обеспечение поддержки новых аппаратных возможностей, доступных на процессорах Intel Xeon.

Например, представьте себе копирование большого объёма инструкций, выполняемое в ходе инициализации PHP 7. На настольных компьютерах для таких операций предпочтительно использовать некэшируемую запись. Такая запись происходит, когда данные попадают напрямую в оперативную память, минуя кэш. Непосредственная запись в память позволяет значительно уменьшить время выполнения операций по копированию больших объёмов данных в ходе инициализации. Однако, учитывая общее ускорение PHP 7, нет ощутимой разницы во времени выполнения при сравнении такого подхода с обычной записью.

Исследования Intel показали, что переход на обычную запись в память на серверах с Intel Xeon v3 даёт увеличение производительности PHP 7 на 2.9% для WordPress, и на 5.9% для MediaWiki. То, что воспринимается на настольных системах с процессорами, оснащёнными 4 Мб LLC, как «загрязнение кэша», оказывается «разогревом кэша» на серверных процессорах с кэшем в 45 Мб. Фактически, это показывает, как большой размер кэша Intel Xeon способен улучшить выполнение некоторых задач.

▍Устранение воздействия на производительность для некэшируемых операций записи

Вышесказанное не означает, что некэшируемая запись в серверных приложениях неактуальна. Она всё ещё востребована в особых случаях, например тогда, когда нужно избежать загрязнения L1 и L2 кэша. Однако, если говорить о фазе инициализации PHP 7, обычная запись предпочтительнее. Именно поэтому патч от Intel задействует в fast_memcpy() обычную запись, как было сделано ранее для memcpy() из libc.

Функция fast_memcpy() в PHP 7 работает быстрее, чем memcpy(). Это происходит потому что в данной функции напрямую реализовано копирование участков памяти, основанное на инструкциях SSE2 без добавления ненужных операций, связанных с выравниванием адресов или проверкой размера. Вместо этого функция fast_memcpy() полагается на тот факт, что области памяти выровнены по 64 байтам. Это справедливо при исполнении на практически любых процессорах. Здесь так же задействованы некоторые дополнительные программные преобразования.

Ограничения, связанные с выравниванием, в fast_memcpy() обычно выполняется только при инициализации. Для частых операций копирования, происходящих во время обычного исполнения программы (в большинстве случаев это касается копирования строк), ограничение на выравнивание не выполняется и здесь стоит пользоваться memcpy() из libc. В это время некэшируемая запись в PHP 7 не используется.

Использование PGO при компиляции PHP: рост скорости для конкретных задач

Профильная оптимизация (Profile-Guided OptimizationPGO) – это техника, которая в настоящее время используется немногими проектами с открытым исходным кодом. Большинство администраторов разворачивают сервера на PHP 7, просто устанавливая уже скомпилированные пакеты. Однако, пользоваться PGO несложно, а в результате можно получить вполне ощутимое улучшение производительности. Мы рекомендуем использовать PGO при компиляции PHP 7.

▍Подсказки для компилятора

При подготовке любой программы компилятор использует эвристические методы определения того, как именно она будет исполняться. Затем код оптимизируется с учётом ранее сделанных предположений. PGO заменяет стандартные эвристические алгоритмы на конкретные статистические показания исполнения. Эти данные получают на этапе профилирования целевого кода, когда он исполняется так, как исполнялся бы при реальной работе. Затем компилятор использует собранные данные в качестве подсказок по оптимизации для того, чтобы получить исполняемый код, лучше настроенный на задачи, которые ему предстоит решать.

С использованием PGO компилятор GCC позволяет получить исполняемый код лучшего качества, в котором учтена интенсивность использования различных частей программы. Редко используемый код при этом перемещается в области памяти, которые используются не часто. В результате оптимизируется использование страниц памяти и кэшей в архитектуре Intel. Кроме того, это ведёт к росту производительности из-за наличия большого объёма кэша L3 у процессоров Intel Xeon v3 и v4. Так как пути исполнения программы оптимизированы, такой подход может привести и к небольшому уменьшению неправильного предсказания ветвлений.

Результаты тщательного тестирование, которые легко можно воспроизвести, полученные в 0-Day Lab Intel, позволили проверить эффективность PGO на реальных сценариях использования PHP. В частности, в 0-Day Lab была исследована производительность обычной сборки PHP 7 в ходе работы WordPress в сравнении с PGO-сборкой, при подготовке которой использовались результаты профилирования кода при исполнении WordPress. Результаты показали рост производительности на 7-8%, при этом никаких изменений в исходный код внесено не было. Исследования Intel привели к тому, что PHP 7 теперь предлагает поддержку сборки профилированного кода.

▍Подготовка PGO-сборок

Развёртывание профилированных сборок – задача сравнительно простая. Вот как подготовить профилированные исполняемые файлы PHP 7 и обучить компилятор для того, чтобы он мог сгенерировать код, оптимизированный для конкретной задачи.

$ make prof-gen # сборка исполняемых файлов профилировщика компилятора для получения статистических данных по исполнению
$ {здесь надо запустить сценарии на PHP с помощью ранее собранного профилировщика для того, чтобы получить статистические данные по исполнению}
$ make prof-clean # очистка файлов и исполняемого кода инструментария
$ make prof-use # перестроение кода с учётом полученных статистических сведений об исполнении

▍Микро-бенчмарки для обучения PGO

Основываясь на результатах экспериментов с PGO, Intel приступила к созданию микро-бенчмарков, которые отражали бы сценарии из реального мира. Эти сценарии могут использовать создатели дистрибутивов, на Linux, например, для подготовки установочных пакетов, которые оптимизированы для различных реальных задач. На GitHub можно найти черновую версию этих обучающих скриптов.

Проект Intel 0-Day Lab

Intel предоставляет PHP-сообществу исчерпывающие сведения об IA, необходимые для оптимизации кода. Проект Intel 0-Day-Lab – это ресурс, который является одним из важнейших инструментов Intel по оптимизации PHP.

В Intel 0-Day-Lab производится ежедневная загрузка исходных кодов PHP, их сборка и измерение производительности. Результаты тестирования, в которых выделены свежие изменения (произошедшие в течение 24-х часов), рассылаются заинтересованным разработчикам. В отчёты входят сведения об изменении производительности в сравнении с тестами предыдущего дня, и предупреждения, если какие-то части кода собрать не удалось. Ежедневные уведомления так же включают в себя сравнение текущей сборки с контрольным релизом. Это позволяет разработчикам ядра видеть, улучшают или ухудшают общую производительность PHP их патчи, даёт им общее представление о том, как PHP развивается в плане производительности.

Двойная скорость и половина памяти: оптимизация PHP 7 - 2
Пример результатов из Intel 0-Day Lab для PHP-скрипта на сервере с процессором Intel Xeon

Для интерпретируемых языков важен каждый процент роста или падения производительности. Так как Intel 0-Day-Lab использует исключительно стабильную платформу для проведения замеров, можно выявить изменения в производительности в районе 1% с относительным среднеквадратичным отклонением менее 0.2%. Со временем подобные небольшие улучшения способны привести к значительному росту производительности.

О качестве проводимых испытаний говорит тот факт, что в феврале 2016 года Zend интегрировала методологию конфигурирования MySQL из 0-Day Lab в собственную внутреннюю систему тестирования. Это, например, позволило на 30% улучшить показатели производительности WordPress.

» Здесь можно больше узнать о проекте Intel 0-Day Lab и подписаться на рассылку.

Инструменты разработчика для оптимизации PHP-кода

В дополнение к сотрудничеству с сообществом PHP-разработчиков, Intel работает и на глобальном уровне, предлагая следующие инструменты, которые нацелены на исследование производительности кода и его оптимизацию:

VTune Amplifier. Набор инструментов, который весьма полезен в деле профилирования кода для архитектур Intel. Программные системы, основанные на PHP, являются хорошими кандидатами на профилирование с помощью VTune.

Branch Hinting Tool. Это аналитический программный пакет с открытым исходным кодом. Он предоставляет дополнительные сведения о ветвлениях в C/C++ приложениях, основываясь на статистических сведениях gcov, полученных в ходе репрезентативного исполнения исполняемых файлов, оснащённых средствами измерения. Этот инструмент применяется для исследования ядра PHP, но с его помощью можно изучать любые C/C++ проекты.

PHP PGO Training Scripts. Набор PHP-скриптов с открытым исходным кодом, созданных Intel. Эти скрипты можно использовать как обучающие сценарии, имитирующие реальную нагрузку при сборке Zend PHP с использованием PGO. Ожидается, что скрипты будут включены в официальный пакет PHP.

Итоги

Для того, чтобы помочь в идентификации проблем производительности PHP и других языков с большими потребностями в памяти, Intel начала глубокий анализ процессорного конвейера. Этот анализ уже позволил выяснить, что рабочие нагрузки, вроде WordPress, тратят от 40% до 50% циклов впустую, на входе в конвейер (Front-End), там, где выполняется выборка и декодирование инструкций. Две основных причины подобных простоев заключаются в промахах ICACHE и ошибках предсказания ветвлений.

Это очень высокий процент простоев. Для оптимальной рабочей нагрузки они не должны превышать 20%. Это – общая проблема, специфичная для интерпретируемых языков, таких, как PHP, так как, повторимся, они часто имеют большую потребность в памяти для исполняемого кода. В настоящее время Intel занимается оптимизацией микроархитектуры, что позволит ускорить исполнение интерпретируемых языков. А именно, планируется добиться следующего:

  • Уменьшить простои на входе в конвейер и задержки, вызванные промахами ICACHE и неправильными предсказаниями ветвлений.
  • Улучшить управление памятью для PHP, HHVM, Python и Node.js.
  • Уменьшить потерю циклов процессора при упреждающем выполнении инструкций (в ситуации, когда инструкции выполняются заранее, основываясь на предсказаниях ветвления, а потом исполнение отменяется).
  • Улучшить общую скорость исполнения интерпретируемых приложений.

Скорость работы приложений зависит и от кода, и от аппаратного обеспечения, а точнее – от того, насколько они друг другу соответствуют, насколько они приспособлены друг к другу. В сущности, взаимодействие Intel и PHP-разработчиков – это поиск способов наиболее рационального взаимодействия всех компонентов серверных решений. И, судя по тому, чего удалось достичь при оптимизации PHP 7 для IA, такой подход позволяет добиться впечатляющих результатов.

В заключение хотелось бы отметить, то, что работа по совершенствованию взаимодействия интерпретируемого кода и аппаратного обеспечения Intel продолжается, причём, касается это не только PHP, но и других программных платформ.

Автор: Intel

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js