Решение Проблемы Мертвого Кода И Включений

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

В частности, мы рассмотрим, как влияют на производительность множественные подключения внешних файлов, наличие «мертвого» кода, ускорение через кэши опкодов и FastCGI для PHP. В какой-то степени статья является следствием темы «Хранение кода в базе данных или сбор кода по кирпичикам» , так как именно после него возникли множественные вопросы по производительности (кстати, его запустили не так давно другой проект построен на указанной технологии хранения всего кода в базе данных).

Одним из преимуществ рассмотренного подхода стала возможность получения на выходе чистого монолитного кода, не содержащего «мертвых» участков и подключений внешних файлов (например, через включать или требовать .

Ниже для простоты мы будем называть это просто «включает»).

Для тех, кто не знаком с этой темой, поясню, что «мертвый» — это код, который заведомо не будет выполняться на странице.

Немного науки.

Вот что говорит о мертвом коде директор Института системотехники РАН, член-корреспондент РАН, один авторитетный парень Виктор Иванников: «Мертвый код — это часть программы или электрической схемы, которая никогда не исполняется, ни при каких условиях, ни при каких входных данных.

Это существенная проблема, особенно для систем с ограниченной памятью.

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

Проблема с мертвым кодом алгоритмически неразрешимый .

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

Заинтересовались этой проблемой в начале 50-х годов.

Соответствующие теорема Райса и теорема Успенского были доказаны одновременно и независимо, только Владимир Андреевич сформулировал ее более широко.

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

Хочу добавить, что в веб-программировании количество мёртвого кода обычно на порядок больше.

При своп-подключении его доля легко превышает порог в 80-90%.

То есть фактически будет выполнена только каждая 20-я строка кода.

Особенно хорошо это видно при использовании «тяжелых» фреймворков.

Сразу введем пару определений, которыми мы будем пользоваться ниже: монолит — код, не использующий внешние файловые соединения (включает) чистый монолит — монолит, в котором нет «мертвого» кода.

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

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

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

Итак, начнем.



Есть проблема?

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

Начнем с мертвого кода.

Создаем страницы с 2000, 5000, 10000 строк кода и ставим на них apacheBenchmark. Мы получаем следующие результаты:

количество строк запросов/сек среднее время на запрос мертвый код
2000 72.24 0.013 0
5000 32.20 0.031 0.6
10000 15.97 0.062 0.75
Здесь и ниже указано время, полученное на старом ноутбуке FS Amilo 1718. Результаты контрольных тестов, проведенных на разных системах с разными ОС и ФС, не отличались пропорционально
Как видите, время, затрачиваемое на обработку скрипта, на самом деле прямо пропорционально количеству строк в нем (что вполне логично, так как поскольку мы ничего не делаем в скрипте, то большая часть времени уходит только на его разбор .

Больше строк означает больше времени на анализ).

Сколько времени на этот раз? Это существенно .

Согласитесь, даже в идеале при отсутствии мёртвого кода 13 тысячных — это очень много (не говоря уже о 62, как в третьем тесте).

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

Теперь посмотрим на включения.

Мы смоделируем 4 ситуации: — «монолит» (без включений и мертвого кода) - «подкачка» (Имитирует безусловное подключение всех библиотек, которые обычно объединяются в большие файлы.

Предполагает мало включений больших файлов .

Много мертвого кода) — «автозагрузка» (Имитирует подключение классов/методов/функций при необходимости (обычно в момент вызова несуществующего класса/метода/функции).

Включает в себя множество включений мелких файлов .

Мертвого кода почти нет) — Пара промежуточных состояний между свопом и автозагрузкой.

Просто ради интереса.

Для полноты картины :) Результаты отображены в следующей таблице (в порядке производительности):

количество строк включения запросов/сек среднее время на запрос мертвый код тип моделирования
2000 0 72.24 0.013 0 чистый монолит
2000 60 35.12 0.028 0 автозагрузка
5000 7 25.63 0.039 0.6
10500 14 13.2 0.076 0.81
15000 5 9.78 0.1 0.87 менять
Как и ожидалось, на первом месте монолит, на втором – автозагрузка с почти двукратным отставанием.

Ну и своп нервно курит в сторонке :) (Правда, это только пока, потом автозагрузку задницу надерёт. Читайте статью дальше).

Но время обработки запроса все еще очень велико.

Кстати, эта таблица как раз подтверждает указанную мной цифру в результирующем выигрыше в 600% при переводе системы на чистый монолит.


Есть проблема – есть решение

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

Наиболее известные системы кэширования (например, PHP) — это электронный акселератор , xCache И БТР .

Для тестирования был выбран eAccelerator, так как он является наиболее распространенным и быстрым в условиях нашей задачи.

Подробно о сравнении систем кэширования можно прочитать здесь.

Здесь .

Вот результаты использования кеша опкода (в порядке производительности):

количество строк включения запросов/сек (без кэша опкодов) запросов/сек с кешем опкода коэффициент ускорения тип моделирования
2000 0 72.24 412.86 5.71 чистый монолит
15000 5 9.78 204.6 20.92 менять
10500 14 13.2 192.2 14.56
2000 60 35.12 112.11 3.19 автозагрузка
И здесь мы видим очень интересные факты.

При использовании кеша опкода, несмотря на огромное количество мертвого кода соединение подкачки оказывается почти в 2 раза эффективнее автозагрузки ! И все благодаря безумному коэффициенту ускорения в 21x. Но коэффициент ускорения автозагрузки оказался самым низким — кэшер опкодов снизил затраты всего в 3 раза.

Отсюда делаем простой вывод: кеш опкода практически решает проблему «мертвого» кода, но не решает проблему включения .

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



А как насчет FastCGI?

По мнению многих, еще один способ ускорить работу скриптов и снизить стоимость загрузки скрипта — запустить PHP в режиме FastCGI. Это не верно! .

Почему fastCGI не ускоряет PHP можно прочитать у Котерова Здесь .

Кстати, его тесты eAccelerator там проводились на примере Zend-фреймворк .

Результаты, полученные Дмитрием Котеровым, очень близки к приведенным в этой теме.



Заключение

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

Как видите, влияние этих факторов весьма существенно.

Статья написана Напольский , по понятным причинам он не смог его опубликовать.

Всё + к его карме ;) Теги: #include #fastcgi #php #Разработка веб-сайтов

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.