Оптимизация производительности и эффективности в больших системах

Узкие места до оптимизации системы
Получив задачу по увеличению производительности, специалисты часто работают со всей системой целиком. Но если в ней сосредоточены сотни микросервисов с миллионами пользователей, то оптимизация ради оптимизации — это путь в никуда. Такую систему можно представить в виде трубы с водой, где есть узкий участок — и именно он будет ограничивать ее производительность. По моему опыту, успешная оптимизация затрагивает не более 10% этой «трубы» для большинства систем.
Поэтому перед началом работ важно построить карту зависимостей и понять, где на самом деле находится проблема. Для поиска узких мест обычно используется профилирование систем или подсистем и опыт специалистов.
Профилирование проводится двумя методами:
- Сверху вниз — начинается от точки входа в систему и постепенно углубляется по дереву вызовов. Этот способ удобен для анализа структуры всей системы и понимания того, какие крупные модули или ресурсы потребляют больше ресурсов.
- Снизу вверх — начинается с конкретных функций, для которых требуется больше всего ресурсов, и далее рассматривается, откуда идет вызов. Такой способ позволяет отметить наиболее ресурсозатратные функции и оптимизировать именно их.
Выбор способа зависит от целей и ресурсов. Например, профилирование всей системы по ключевым бизнес-сценариям — от приложения и до работы СУБД — может занять несколько месяцев. Поэтому, если время ограничено, лучше провести профилирование методом «снизу вверх».
Однако такой метод не всегда может показать все узкие места. Например, в Яндекс Go мы тщательно профилировали основные сценарии приложения методом «сверху вниз», что позволило найти несколько узких мест, которые мы бы не нашли методом «снизу вверх».
Неочевидные местоположения оптимизаций
Порой оптимизации, которые значительно увеличат производительность, находятся между подсистемами — и их сложно заметить при подходе «снизу вверх». Такой метод заставляет сфокусироваться на локальных улучшениях отдельных компонентов — но при этому из виду упускаются возможности оптимизации на стыке подсистем.
Отдельные улучшения могут дать 50% результата за 10% времени, но оставшиеся 50% требуют многократно более дорогой переработки логики API. Например, мы решили улучшить производительность конкретного API на бэкенде и в мобильном приложении. Специалисты задешево получили результат, максимально оптимизировав работу API на отдельных участках. Но чтобы удвоить этот результат, требовалось полностью переработать логику API, что заняло многократно больше времени, чем точечная оптимизация.
Также многие оптимизации могут лежать в «серых» зонах ответственности — особенно если система состоит из сотен микросервисов. Например, такая функция, как стартовая анимация при запуске приложения может быть не закреплена ни за одной из команд, так как в ней уже несколько лет не делались правки. Но именно оптимизация этой функции может стать самой эффективной — поэтому оптимизации системы с декомпозицией по зонам ответственности может быть недостаточно.

Оптимальная стратегия — это сначала определить системные точки перегрузки «сверху вниз», а затем детализировать оптимизацию «снизу вверх», чтобы избежать ситуации, когда команды тратят ресурсы на локальные улучшения, но упускают возможность радикально ускорить систему за счет изменений в ее логике.
Оптимизация и надежность
При любой оптимизации главным критерием остается сохранение надежности и безопасности системы. Если система становится нестабильной и уязвимой, то оптимизация теряет всякий смысл, потому что изменения могут стоить потери данных или резкого уменьшения лояльности.
На практике это означает, что любые преобразования должны проверяться на отказоустойчивость. Это может занять больше времени — например, в Яндекс Go 80% времени для части оптимизаций занимала не сама оптимизация, а обеспечение ее надежности. Это необходимо для стабильности и устойчивости системы к нагрузкам.
Также нужно быть готовыми к тому, что самые эффективные оптимизации обычно ухудшают какие-то функции. Например, можно ускорить загрузку приложения на 30%, при этом понизив маркетинговый охват внутренних промо-блоков на 10% — и в таком случае нужно решить, что важнее. А в некоторых сложных случаях нам с командой приходилось отыгрывать ухудшения продуктовых метрик за счет одновременного их улучшения в соседних местах.
Производительность как культура
Улучшение производительности — это лишь полпути. Вторая половина — это сохранение полученного результата в течение следующих пяти лет. Чтобы выполнить эту задачу, необходимо внедрить практики на уровне команд.
Я рекомендую использовать следующие принципы:
- Определение бюджета на производительность. Это означает установку целевой скорости для системы и конкретных числовых целей, которых необходимо придерживаться для сохранения этой скорости.
- Наблюдаемость. Метрики, логи и трассировки должны помогать быстро увидеть отклонения, пока они не превратились в инциденты.
- Культура постмортемов. При нарушении SLO необходимо разбирать его причины и извлекать уроки из инцидента.
Культура производительности в команде помогает максимально сохранить эффект оптимизации даже при значительном росте нагрузки, изменениях в бизнес-логике и масштабировании команды.
В заключение
Чем проще система, тем легче находить и устранять в ней узкие места. Сложные архитектуры с множеством компонентов затрудняют поиск и анализ проблем — поэтому простота становится здесь не компромиссом, а стратегией.

Именно поэтому в Yandex Go, где число микросервисов превысило 800, было принято решение начать переход к DOMA (domain-oriented microservice architecture). В рамках DOMA сервисы группируются вокруг предметных областей, а взаимодействие между ними строится по узким интерфейсам. Это упрощает наблюдаемость, повышает устойчивость к сбоям и дает разработчикам более прозрачное понимание того, где именно возникают узкие места.
Простота архитектуры — это инвестиция в долгосрочную эффективность. Чем понятнее и предсказуемее система, тем быстрее она адаптируется под новые нагрузки, тем меньше стоимость изменений и тем надежнее она работает в масштабе.
Опубликовано 16.11.2023


