Производительность
Приложение должно оставаться отзывчивым: кадры отрисовываются вовремя, память не растёт бесконечно, запуск не испытывает терпение пользователя, а размер загрузки не отпугивает его ещё до первого экрана.
Почему это важно. Пользователи производительность не измеряют, а оценивают — и оценивают строго. Время запуска и плавность прокрутки влияют на удержание напрямую, сильнее почти любой функции. Загвоздка в том, что оптимизировать не то хуже, чем не оптимизировать вовсе: время потрачено, сложность выросла, выигрыша нет.
Что нужно понимать
- Есть ли измеренная проблема — или только подозрение
- Какой бюджет не выдерживается: время кадра, память, запуск, размер
- Куда на самом деле уходит время — по профилю, а не по интуиции
- Стоит ли исправление той сложности, которую оно добавляет
- Осталось ли оно исправленным через месяц
Ключевые темы
Кадры
- Бюджет кадра: 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 — границы перерисовки, стоимость прозрачности и обрезки, а также конкретные виджеты, которые обходятся дорого.