Перейти к основному содержимому

Производительность

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

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

Что нужно понимать

  • Есть ли измеренная проблема — или только подозрение
  • Какой бюджет не выдерживается: время кадра, память, запуск, размер
  • Куда на самом деле уходит время — по профилю, а не по интуиции
  • Стоит ли исправление той сложности, которую оно добавляет
  • Осталось ли оно исправленным через месяц

Ключевые темы

Кадры

  • Бюджет кадра: 16 мс при 60 Гц, 8 мс при 120 Гц
  • Build, layout, paint, raster — и какая из фаз выходит за бюджет
  • Рывки из-за дорогого build и из-за слишком широких перестроений
  • Рывки от компиляции шейдеров и что здесь изменил Impeller
  • Длинные списки: ленивое построение, известная высота элемента, дешёвые элементы

Память

  • Утечки: контроллеры, подписки и слушатели, которые никто не освободил
  • Изображения как основная статья расходов и декодирование под размер отображения
  • Кэши без ограничения размера
  • Чтение профиля памяти и умение отличить рост от шума

Запуск

  • Холодный, тёплый и горячий старт — три разных числа
  • Работа, которая делается до первого кадра, хотя могла бы не делаться
  • Отложенная инициализация и то, что действительно обязано блокировать
  • Разрыв между нативным splash-экраном и первым настоящим кадром

Размер

  • Что на самом деле лежит в сборке
  • Ресурсы, шрифты и четыре начертания, которыми никто не пользуется
  • Отложенные компоненты и сборки под конкретную платформу
  • Измерение, а не догадки о том, что выросло

Методика

  • Режим profile: в debug цифры не значат ничего
  • Реальные устройства, и в первую очередь самое дешёвое из тех, что есть у ваших пользователей
  • Замеры до и после, с записанными числами
  • Отслеживание регрессий, чтобы исправленное таким и осталось

Уровни

УровеньКак это выглядит
JuniorЗамечает, что экран тормозит. Применяет известные хорошие практики — const, ленивые списки — не измеряя.
MiddleПрофилирует, чтобы найти причину, отличает проблемы UI-потока от проблем растрового, устраняет утечки и стоимость изображений, измеряет результат.
SeniorЗадаёт бюджеты, отслеживает регрессии во времени и может сказать, что оптимизировать, а что оставить в покое.

Практика

Для начала

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

  • Почините изображение Найдите картинку, которая декодируется намного крупнее, чем показывается, и ограничьте её размер. Измерьте память.

  • Найдите утечку Откройте и закройте экран пятьдесят раз и посмотрите, возвращается ли память к исходному уровню.

Дальше

  • Сделайте список плавным Возьмите список, который дёргается, и доведите его до стабильного времени кадра — с числами до и после.

  • Сократите холодный старт Измерьте холодный старт на слабом устройстве и уберите работу с критического пути.

  • Следите за этим во времени Добавьте замер производительности в CI, чтобы регрессия была видна до релиза.

Проверьте себя

  • Сколько длится холодный старт на самом дешёвом устройстве, которое есть у ваших пользователей?
  • Какой экран в приложении теряет больше всего кадров и откуда вы это знаете?
  • Худшие рывки у вас в UI-потоке или в растровом?
  • Возвращается ли память к исходному уровню после закрытия тяжёлого экрана?
  • Что занимает больше всего места в сборке приложения?
  • Какое число о производительности вы отслеживаете от релиза к релизу?

Материалы

  • Performance best practices — официальный список, с редким достоинством: здесь сказано, какие пункты действительно важны, а какие остались фольклором.
  • Flutter performance profiling — как читать timeline и отличить проблему UI-потока от проблемы растрового; от этого зависит всё дальнейшее решение.
  • DevTools — профилировщик CPU, обзор памяти и инструмент анализа размера приложения. Последним, кстати, пользуются незаслуженно редко.
  • Impeller — движок рендеринга и то, что он изменил в рывках от компиляции шейдеров: раньше это была самая частая причина подтормаживаний при первом запуске.
  • Improving rendering performance — границы перерисовки, стоимость прозрачности и обрезки, а также конкретные виджеты, которые обходятся дорого.