Главное Авторские колонки Вакансии Образование
765 0 В избр. Сохранено
Авторизуйтесь
Вход с паролем

Как улучшить производительность PHP для веб-приложений

Программистам очень нравится последняя версия PHP — одного из наиболее быстрых языков сценариев. В этом можно убедиться, прочитав, например, статью Сравнение производительности PHP 7.0 и HHVM на Хабрахабре или статью на английском языке “PHP 7 vs HHVM – Which One Should You Use?”
Мнение автора может не совпадать с мнением редакции

Однако поддержание оптимальной производительности PHP — это не только быстрое выполнение кода. Лучший инструмент для улучшения производительности PHP не найти среди готовых программ. Необходимо знать, на какие именно проблемы производительности обратить внимание и как их решать. В этой статье мы постарались собрать все, что нужно для успешной работы с PHP-приложениями.

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

Краткая история PHP

PHP — это язык сценариев, изобретенный Расмусом Лердорфом (Rasmus Lerdorf) в 1995 году. Первоначально этот язык разработчики написали для себя. Поэтому язык получил соответствующее название PHP как аббревиатуру от “Personal Home Page” — «Личная Домашняя Страница».

В ходе дальнейшей работы над языком Лердорф существенно расширил функциональность PHP, поэтому считается, что PHP теперь является рекурсивной аббревиатурой от “PHP: Hypertext Preprocessor” — «PHP: Гипертекстовый Препроцессор».

За последние два десятилетия группа разработчиков PHP улучшила производительность PHP в следующих направлениях:

1. Прежде всего, в 1999 году появился новый PHP-движок Zend Engine;

2. В 2000 году вышел PHP 4, который включал компилятор в памяти и модель исполнителя, что позволило использовать PHP для создания динамических веб-приложений;

3. В 2004 году был выпущен PHP 5. Кроме прочего - обновилось ядро Zend (Zend Engine 2), что существенно увеличило эффективность этого интерпретатора;

4. В 2015 году появился обновленный PHP 7.0 с улучшенным движком Zend Engine и уменьшенным потребления памяти;

5. В момент написания статьи доступна новейшая версия PHP 7.1 от декабря 2016 года. Веб-сайт классов PHP содержит подробное описание всех изменений, внесенных между PHP 5 и PHP 7.1 (также в Википедии ).

Что такое действительно хорошая производительность PHP?

Следует иметь ввиду, что производительность и скорость - не являются синонимами. Оптимальная производительность балансирует между скоростью, безошибочностью и масштабируемостью. Например, при написании веб-приложения придется выбирать между двумя приоритетами:

1) приоритетом скорости, написав скрипт, который заранее загружает все в память;

2) приоритетом масштабируемости со скриптом, который загружает данные блоками.

Следующий рисунок 1 взят из английской статьи на сайте . На нем показан теоретический компромисс между скоростью и масштабируемостью.

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

Рис. 1. Теоретический компромисс между скоростью и масштабируемостью

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

Получаем, что когда трафик превышает определенный порог, сценарий для скорости становится медленнее сценария для масштабируемости . Этот порог хорошо виден на рисунке как пересечение красной и синей линий.

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

Когда следует начинать оптимизировать PHP-код?

Опытные программисты время от времени сохраняют протестированный код, заканчивая тем самым цикл проекта. Но это разумно делать только при хорошей производительности PHP-приложения!

Как добиться хорошей производительности PHP-приложения? Необходимо проводить тесты во время процесса разработки. Иначе придется переписывать большие блоки кода, чтобы заставить приложение нормально функционировать.

Оптимизировать PHP-код следует начинать перед созданием PHP-приложения! Необходимо сразу оценить состояние вашего железа и программного обеспечения, чтобы определить параметры их производительности. Эта информация при кодировании приложения позволит оценить риски и выигрыш конкретных компромиссов. Причем необходимо использовать адекватные тестовые данные, иначе код приложения окажется бесперспективным.

Советы по оптимизации PHP-скриптов

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

1. Используйте готовые функции PHP

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

2. Используйте JSON вместо XML

Функции PHP json_encode() и json_decode() просто невероятно быстры. Поэтому использование JSON предпочтительнее использования XML.

Если вам все же приходится разбираться с XML, лучше использовать шаблонные регулярные выражения, чем манипуляции с DOM.

3. Используйте методы кэширования

Кэш-память особенно полезна для сокращения объема загружаемых данных.

Кэширование байт-кода с помощью APC или OPcache сильно экономит время выполнения скомпилированного сценария.

4. Уберите лишние вычисления

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

5. Используйте isset()

Проводите сравнения с помощью пар count(), strlen() и sizeof(), isset(). Это быстрый и простой способ поиска значений, больше нуля.

6. Отключите ненужные классы

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

7. Отключите отладочные сообщения

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

8. Закрывайте соединения с базой данных

Сбрасывание переменных и закрытие соединений с базой данных сэкономит драгоценную память.

9. Ограничьте обращения к базе данных

Старайтесь использовать совокупности запросов к базе данных. Это сокращает количество обращений к базе данных, приложение будет работать быстрее.

10. Используйте строковые функции Str

str_replace быстрее, чем preg_replace, а strtr в четыре раза быстрее, чем str_replace.

11. Используйте одинарные кавычки

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

12. Используйте три знака равенства

Поскольку «= = =» проверяет величины только одного типа, это делает оператор сравнения «= = =» более быстрым, чем оператор «= =».

Узкие места производительности PHP

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

1. Сеть

Один из очевидных источников узких мест — это сети. Может просто не хватить ресурсов сети для обработки передаваемого объема данных.

2. Центральный процессор

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

3. Совместно используемая память

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

4. Файловая система

Файловая система со временем становится фрагментированной. Поэтому используйте файловый кэш RAM, который ускорит доступ к диску, если этот кэш достаточного размера.

5. Управление процессами

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

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

6. Другие серверы

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

Еще советы по улучшению производительности PHP

1. Используйте расширение ядра Zend OPCache

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

Zend OPCache — это расширение, которое сохраняет скомпилированный код в памяти. Это позволяет PHP в следующий раз при выполнении кода проверять разметки времени и размеры файла, чтобы определить, были ли части исходного файла изменены. Если таких изменений не было, то будет запущен сохраненный код.

Более подробную информацию можно получить в статье на Хабрахабре «PHP Performance Series: Caching Techniques»

На рисунке 2 показано различие во времени выполнения и использовании памяти между PHP-приложением, выполняемым: 1) без кэша; 2) с OPcache; 3) с eAccelerator (другой инструмент PHP-кэширования).

Правый график показывает время выполнения в миллисекундах (Execution Time (ms)), левый — использование памяти в мегабайтах (Memory usage (mb)). Столбики синего цвета соответствуют отсутствию кэширования, красного — кэшированию OPcache, зеленого — кэшированию eAccelerator.

Из рисунка 2 следует, что кэширование OPcache снижает как время выполнения, так и использование памяти примерно в два раза по сравнению с отсутствием кэширования. Кэширование eAccelerator немного уступает кэшированию OPcache.

Рис. 2. Столбиковые диаграммы различия во времени выполнения и использовании памяти между PHP-приложением, выполняемым без кэширования, с OPcache и с eAccelerator

2. Выявите задержки базы данных

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

Удостоверьтесь, что лог медленных запросов SQL включен, чтобы иметь возможность выявить их. Затем изучите эти медленные запросы, чтобы оценить их эффективность. Если обнаружится, что выполняется слишком много запросов или одни и те же запросы необоснованно повторяются, внесите соответствующие изменения. Такие изменения должны повысить производительность приложения, сокращая время доступа к базе данных.

Как узнать, какие из запросов выполняются дольше всего? Более подробно см. статью на Хабрахабре «Как выявить медленные SQL запросы?», URL: https://habrahabr.ru/post/31072/

3. Очистите файловую систему

Проанализируйте файловую систему на неэффективность, то есть удостоверьтесь, что файловая система не используется для хранения сессий. Самое главное - внимательно следите за функциями статистики файлов: file_exists(), filesize() и filetime(). Попадание этих функций внутрь цикла приводит к проблемам с производительностью.

4. Тщательно контролируйте показ API

Большинство веб-приложений, которые зависят от внешних ресурсов, используют удаленный API. Хотя удаленный API находится вне вашего контроля, однако можно смягчить проблемы API-производительности. Например, можно кэшировать API-вывод или делать фоновые вызовы API. Установите разумные интервалы для API-запросов и, если это возможно, показывайте на дисплее API-вывод без ответа API.

5. Профилируйте PHP

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

Xdebug рассматривается в статье на Хабрахабре «Introducing xdebug»

Необходимо уметь контролировать производительность PHP

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

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

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

Перспективы улучшения производительности PHP

Эволюция PHP продолжается. Новейшее изменение в разработке PHP 8 — это добавление компиляции «на лету», или JIT-компиляции, которая позволит создавать еще более быстрые веб-приложения. Так как темп технологического прогресса растет, растут ожидания пользователей. Поэтому разработчики должны всегда внимательно следить за последними изменениями.

Технология JIT-компиляции описана в Википедии.

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

+1
В избр. Сохранено
Авторизуйтесь
Вход с паролем