Автор: Се Вэй (Вэй Шэн)
Разный бизнес-опыт приводит к разным техническим требованиям. «Отличный пользовательский опыт» - это неустанное стремление Таоте. В этой статье будут представлены многие методы оптимизации, которые автор использовал во Flutter с момента присоединения к Taote. Эти оптимизации не включают преобразование двигателя, не требуют конструкции «высокого колеса». ", если тщательное и тщательное углубленное извлечение информации о бизнесе, придерживающееся фактической соматосенсорной ориентации, может значительно улучшить взаимодействие с пользователем, и разработчики Flutter достойны применить его к каждому пикселю продукта.
задний план
Таотэ имеет три отличительные характеристики:
- Бизнес-функции: Taote имеет самые сложные связи электронной коммерции на основе Tao в отрасли.
- Характеристики пользователей: Среди пользователей Taote большое количество пользователей среднего и пожилого возраста, большое количество пользователей имеют более низкие версии системы мобильных телефонов, и большое количество пользователей использует недорогие телефоны.
- Технические характеристики: Taote использует технологию кроссплатформенного рендеринга Flutter в больших масштабах.
В итоге:
Самая сложная бизнес-связь + группа пользователей с самой низкой производительностью + новейшая кросс-платформенная технология ==> одна из основных проблем: беглость страниц серьезно затруднена.
Флаттер основная ссылка | Частота кадров быстрой прокрутки 20 сек. | Скорость сваливания (частота заиканий в секунду) |
---|---|---|
Вкладка "Живое" | 27 | 7.04% |
мой | 41.3666 | 7.63% |
Подробности | 26.7 | 15.58% |
Примечание. Соответствующие данные основаны на естественных условиях Y67, Taote.
3.32.999.10 (103) мерная
Цель
Беглость – ключевой элемент взаимодействия с пользователем. Никто не хочет, чтобы мобильные телефоны использовались для просмотра фильмов или прокрутки PPT. Особенно сейчас популярность экранов с высокой скоростью пролистывания (90/120 Гц) значительно усилила восприятие пользователями беглости. ., но беглость также тесно связана со сложностью продукта, а также является компромиссом между сложностью и простотой.Первый этап целей оптимизации беглости Taote:
Страница ссылок ядра Flutter достигает высокой плавности (средняя частота кадров: 45 кадров в секунду для слабых машин, 50 кадров в секунду для машин среднего уровня, 50 кадров в секунду для машин высокого класса)
Состояние после первого этапа оптимизации
иметь значение | средняя частота кадров | Ставка сваливания | эффект усиления |
---|---|---|---|
1. Рекомендация вкладки Live и столбцы классификации | 46.0 | 0.35% | Частота кадров увеличена на 19 кадров, а частота стоп-кадра снижена на 6,7%. |
2. Моя страница | 46.0 | 0% | Частота кадров увеличена на 4,6 кадра, а частота стоп-кадра снижена на 7,6%. |
3. Детали | 45.0 | 2% | Частота кадров увеличена на 18,3 кадра, а частота стоп-кадра снижена на 13,58%. |
Старая версия 3.32 показана слева от видео, а новая версия 3.37 показана справа от видео. Поскольку инструмент uiautomator вызовет ПРОБЛЕМУ производительности специальных возможностей, эта версия сравнивается с ручным тестированием.
Смотрите видео по адресу:Практика оптимизации беглости Taote Flutter
В дополнение к очевидному улучшению данных, с точки зрения соматосенсорики, старая версия быстрой прокрутки явно застревает, и изображение имеет резкие изменения, в то время как новая версия в основном устраняет очевидное застревание, а изображение непрерывное и стабильное.
вопрос
Вернемся к самой технологии, почему Flutter зависает и низкая частота кадров? В общем причин две:
- Поток пользовательского интерфейса медленный -> команда рендеринга медленная
- Поток графического процессора медленный -> растеризация медленная, композиция слоев медленная, а пиксели на экране медленные
Итак, как решить две вышеупомянутые проблемы, находится в центре нашего внимания. Теперь, когда мы знаем, что есть проблема с определенной частью, у нас, естественно, есть инструменты для систематического измерения уровня проблемы, а также систематическая теоретическая поддержка практики.Давайте рассмотрим следующие два раздела.Процесс чередуется с практикой. соответствующие стратегии в Таотэ.Сочетание теории и практики лучше для понимания.
как решить
Решение - Кейс
Опустите триггерный узел setState
Механизм обновления Flutter известен всем: на более высоком уровне дерева виджетов срабатывает setState, чтобы пометить грязный элемент, «чем больше грязное дерево», а чем ниже уровень и чем более локальный виджет запускает обновление состояния, «тем меньше грязное дерево», помечен как Element. Rebuild будет запущен после того, как дерево станет грязным, обходя дерево компонентов. Принцип см. на следующем рисунке «Анализ исходного кода механизма обновления страницы Flutter»:
Для «Анализ исходного кода Element.updateChild» см. оптимизацию 2 ниже.
Возьмем, к примеру, Таотэ. В качестве примера возьмем функцию предварительного просмотра видео на вкладке «Живое». Первоначально индекс воспроизведения видео на вкладке «Живое» передается подкомпонентам через состояние слой за слоем. Как только состояние изменяется, setState верхнего уровня запускает обновление. индекса воспроизведения, что приводит к обновлению всей страницы. Но на самом деле, только "исходный видеовиджет, который нужно приостановить" и "видеовиджет, который нужно воспроизвести" нужно только обновить состояние всей страницы. Мы меняем механизм мониторинга, все видеовиджеты на странице регистрируются для мониторинга, а верхний уровень использует EventBus для равномерного распределения индекса воспроизведения по каждому видеовиджету, локальное изменение его состояния после проверки виджета.
Другим примером является страница сведений, благодаря использованию функции «заимствования картинок с предыдущей страницы» заимствованные картинки скрываются после контроля прокрутки, но вызывающий узел setState размещается в виджете верхнего уровня детали, что приводит к глобальному обновлению. Фактически, логика обновления мониторинга может быть делегирована «заимствующему компоненту изображения», чтобы уменьшить размер «грязного дерева».
Кэшировать неизменяемые виджеты
Есть два основных преимущества кэширования неизменяемых виджетов. 1. Кэшированный виджет не нужно будет создавать повторно.Хотя официально Flutter считает, что виджет — это очень легковесный объект, в реальном бизнесе по-прежнему распространено слишком большое время сборки. 2. Возврат того же виджета, на который ссылаются, заставит Flutter остановить последующий обход поддерева, то есть Flutter считает, что поддерево не имеет изменений и не нуждается в обновлении. Принцип см. на следующем рисунке "Анализ исходного кода Element.updateChild"
В качестве примера сценария приложения используется реальная страница Taote. Некоторые компоненты на странице сведений используют DXWidget. Теоретически после создания содержимого компонента жизненный цикл страницы не изменится. В этом случае неизмененный виджет можно кэшировать, чтобы избежать повторного динамического рендеринга DX и остановить обход поддерева.
Компонент Item фида имеет сложную компоновку и высокую стоимость создания. Теоретически содержимое не изменится после его создания один раз, но элемент может быть удален. В этом случае следует использовать Objectkey для уникальной идентификации компонент для предотвращения смещения состояния.
Уменьшить ненужную сборку (setState)
Вкладка Live использует скрытую точечную экспозицию компонента.После проверки DevTools обнаружил, что он воссоздает itemWidget при каждом обратном вызове прогресса.Хотя это не вызовет бизнес-исключений, теоретически, itemWidget нужно создать только один раз.Строитель функция неправильно передается при использовании компонента, а не непосредственно экземпляра itemWidget.
Логика страницы деталей очень сложная, AppBar вычисляет прозрачность в реальном времени по расстоянию прокрутки, что приведет к частому setState, на самом деле состояние должно обновляться только после разницы между изменениями прозрачности и прозрачностью. Из соображений производительности должно быть только несколько типов прозрачности изменения значений.
Отделение переменных слоев от неизменяемых слоев
В повседневной разработке часто встречается, что большинство элементов на странице остаются неизменными, а какой-то элемент меняется в режиме реального времени. Например, Gif, анимация. В это время нам нужен RepaintBoundary, но и синтез самостоятельных слоев потребляет, что нужно измерять и улавливать. Возьмем, к примеру, Тао Тэ.
Gif-изображение в прямой трансляции постоянно бьется с высокой частотой, из-за чего будет перерисовываться один и тот же слой страницы. В это время вы можете обернуть изменяемый компонент Gif с помощью RepaintBoundary, пусть он будет в отдельном слое, а затем, наконец, объедините его с другим слоем на экране.
Точно так же обратный отсчет seckill также является распространенной сценой в электронной коммерции, и этот компонент также подходит для сцены RepaintBoundary.
Избегайте частых триггеров
Из-за AliFlutter мы можем активно запускать DartGC, но GC также потребляет, особенно для высокочастотного GC. До Taote, из-за нехватки памяти в iOS, ScrollEndNotification будет запускать GC, когда прокрутка списка останавливается, а ScrollEndNotification будет запускаться один раз после каждого события руки Down->up.Если пользователь касается несколько раз, GC будет запускаться чаще. производительность Y67 около кадров 4. Этот блок увеличивает GC, когда страница не видна, и закрывает скользящий GC на слабых машинах Android, таких как Y67, для повышения производительности скользящего.
Большая подпоточность разбора JSON
Изолят Flutter по умолчанию является однопоточной моделью, и все операции с пользовательским интерфейсом выполняются в потоке пользовательского интерфейса.Если вы хотите применить преимущество многопоточности, вам нужно открыть новый изолят или вычислить. В любом случае await, scheduleTask просто задерживает время вызова задачи и по-прежнему занимает «поток пользовательского интерфейса», поэтому при анализе большого Json или большого количества вызовов канала обязательно наблюдайте за потреблением потока пользовательского интерфейса. В Taote мы включаем синтаксический анализ и вычисления json на слабых машинах, не блокируя поток пользовательского интерфейса.
Сведите к минимуму или понизьте использование таких компонентов, как «Обрезка» и «Непрозрачность».
Во Flutter Clip в основном используется для обрезки, обрезки прямоугольников, прямоугольников со скругленными углами и кругов. После вызова все последующие инструкции по рисованию будут затронуты его Clip. Некоторые ClipRRects можно заменить на ShapeDecoration, а Opacitiy можно заменить на AnimatedOpacity.Обрезка изображений может быть реализована путем настройки библиотеки изображений Transform.
Понизьте предварительно обработанную область CustomScrollView до разумного значения.
По умолчанию CustomScrollView не только отображает содержимое экрана, но также отображает содержимое компонентов в верхней и нижней областях 250, то есть, например, поток водопада с двумя столбцами, текущий экран может отображать 4 компонента, и в верхнем и нижнем состояниях отображения по-прежнему 4 компонента.Если setState (когда больше загружено), есть 8 перерисовок компонентов. Фактический пользователь видит только 4, на самом деле ему нужно отобразить только 4, а скольжение вверх и вниз также вызовет создание и уничтожение внеэкранных виджетов, что приведет к зависанию прокрутки. Высокопроизводительные мобильные телефоны могут быть предварительно визуализированы, и Taote снижает это расстояние до 0 или меньше на недорогих телефонах.
Пакетная работа канала с высокочастотной скрытой точкой
Это очень распространенное поведение — сообщать о скрытых точках, когда компонент открыт, но в сценарии с быстрой прокруткой, если 10+ элементов пропускаются в одно мгновение, вызовы 20+ каналов также будут занимать определенное количество ресурсов потока пользовательского интерфейса и Собственные ресурсы потока пользовательского интерфейса. Здесь Таоте выполнила пакетную и запланированную загрузку для некоторых сценариев и поддерживает очередь скрытых точек. Время по умолчанию — 3 с или 50, и сообщается, когда бизнес не виден. Объединенные вызовы по 20+ каналам объединяются в один вызов. Бизнес также может заставить очередь сбрасывания сообщать в подходящее время и в то же время на стороне Native переключить поведение захоронения на подпоток.
Другие эффективные меры оптимизации
Некоторые бизнес-спецэффекты и деловая занятость могут быть умеренно ухудшены на недорогих устройствах.Например, Taote уменьшил время задержки воспроизведения предварительного просмотра видео с 500 мс до 1,5 с, а пороговое расстояние предварительной загрузки потока с 2000+ до 500. Идея снижения качества таких мер, как уменьшение угла до прямого угла, заключается в том, чтобы сначала убедиться, что пользователи самого низкого уровня могут использовать его плавно, а затем украсить детали, чтобы добавить глазурь на торт.
Когда Flutter включен для специальных возможностей, возникает проблема с производительностью в сцене быстрой прокрутки.Например, если определено, что бизнес не нуждается в специальных возможностях или пользователь активирует специальные возможности по ошибке, вы можете добавить виджет ExcludeSemantics, чтобы заблокировать доступность.
Благодаря обнаружению DevTools было обнаружено, что обнаружение частоты кадров high_available с высокой доступностью имеет проблемы с производительностью в старой версии.Его можно обновить для версии подключаемого модуля или низкоуровневого компьютера, чтобы заблокировать обнаружение.
Решение — сводка вариантов оптимизации
Приведенные выше десять практик оптимизации, независимо от деталей, можно условно разделить на следующие категории.
Как улучшить производительность потока пользовательского интерфейса:
-
Как улучшить производительность сборки
-
Уменьшите начальную точку обхода и уменьшите секцию триггера setState
-
Остановить обход дерева, неизменный контент, вернуть тот же экземпляр компонента, Flutter прекратит обход дерева (SlideTransition)
-
Уменьшить ненужную сборку (setState)
-
-
Как улучшить производительность макета
- Макет не подвержен проблемам на данный момент
-
Как улучшить характеристики краски
- RepaintBoundary разделяет переменные и неизменяемые слои, такие как GIF-файлы, анимация, но многослойный композитинг также имеет накладные расходы.
-
разное
-
Методы, отнимающие много времени, такие как синтаксический анализ больших объемов данных JSON, выполняются в виде подпотоков с вычислением.
-
Сократите ненужные вызовы каналов или пакетные слияния
-
уменьшить анимацию
-
Уменьшить журнал при выпуске
-
Улучшение приоритета потока пользовательского интерфейса на Android/iOS
-
Компонент списка поддерживает частичную сборку
-
Меньшее значение cacheExtent уменьшает диапазон рендеринга.
-
Как улучшить производительность потоков графического процессора:
- Осторожно, сохраните слой
- Свернуть ClipPath. После вызова все последующие инструкции по рисованию должны пересекаться с Path. (КлипРект, КлипРрект и т. д.)
- Уменьшить матовое стекло BackdropFilter, shadow boxShadow
- Уменьшите использование непрозрачности и при необходимости используйте AnimatedOpacity.
Решение — измерительный инструмент
Если рабочий хочет хорошо работать, он должен сначала заточить свои инструменты. Инструменты в основном делятся на следующие две части.
- Обнаружение беглости: существует несколько схем определения беглости, которые не нужно вторгаться в код.Вы можете получить данные SurfaceFlinger через adb, выполнить сравнение изображений на основе VirtualDisplay или использовать официальные DevTools. Третья сторона более зрелая, такая как PerfDog.
- Устранение неполадок Caton: DevTools — официальный инструмент разработки, очень практичный
- Производительность определяет время процессора для одного кадра (сборка, компоновка, рисование), время графического процессора и время сборки виджета.
- Метод обнаружения CPUProfiler требует много времени
- Рабочий инспектор наблюдает необоснованный макет
- Память мониторов Дартская память
DevTools
Flutter разделен на три режима компиляции: Debug/Release знаком всем, самая большая особенность Debug — возможность отладки HotReload, Release — самая высокая производительность, Run и сохранение множества методов анализа производительности.
Как запустить флаттер в режиме профиля?
Если это смешанный проект, на примере Android вы можете добавить профиль {инициировать с отладкой} в app/build.gradle, Некоторые ресурсы приложения могут различать отладку/профиль, и вы также можете скопировать профиль. Конечно, для более хакерского и более тщательного способа вы можете напрямую изменить метод buildModeFor в файле $flutterRoot/packages/flutter_tools/gradle/flutter.gradle, чтобы он по умолчанию возвращал желаемый режим Profile/Release.
Как открыть DevTools в режиме профиля?
Рекомендуется использовать flutter attach IDE или командную строку, чтобы использовать инструменты разработки flutter pub global run, заполнить адрес обсерватории, и вы можете начать использовать DevTools.
Flutter Performance&Inspector
Взяв в качестве примера AS, справа появятся две функциональные области: Flutter Performance и Inspector. Область функций производительности выглядит следующим образом:
Эффект наложения показан ниже. Видно, что есть 2 строки гистограмм, верхняя часть-это потребление времени кадра графического процессора, а нижняя часть-потребление времени процессора.Последние 300 кадров отображаются в режиме реального времени.Когда текущее время кадра превышает 16 мс, зеленая линия сканирования станет красной Этот график часто используется для наблюдения «Точка мгновенного замораживания» в динамическом процессе.
Инспектор относительно прост, вы можете просматривать структуру дерева виджетов и реальную структуру дерева рендеринга, включая базовую информацию о макете, а инспектор в DevTools содержит более подробную информацию.
DevTools&Flutter Inspector
DevTools&Performance
Функция «Производительность» — это основной инструмент для оптимизации производительности.Здесь вы можете проанализировать причины, по которым большинство потоков пользовательского интерфейса и потоков графического процессора зависают. Для удобства анализа эта цифра получена в режиме Debug, а собственно анализу производительности подлежит режим Profile.
Как показано на Рисунке 1 выше, функция Build занимает слишком много времени, и это происходит в течение десятков последовательных кадров.Должна быть серьезная проблема с логикой Build. Теоретически Widget не нужно перестраивать, если его состояние не изменилось после создания один раз. Из предыдущего случая Taote видно, что бизнес-ошибка на самом деле вызвана повторным созданием виджетов в обратном вызове процесса прокрутки. Фактическая сборка должна быть создана и выполнена только 2 раза в логике каскадного макета.
Детали функции рисования можно включить в режиме отладки с помощью параметра debugProfilePaintsEnabled=true. Когда изменяемые элементы и неизменяемые элементы смешиваются в одном и том же слое, это может привести к чрезмерному повторному рисованию всего слоя.Если содержимое элементов не меняется, функция рисования не должна тратить время на отрисовку избыточных элементов. С помощью вышеупомянутого переключателя Repain RainBow или debugRepaintRainbowEnabled=true ситуацию перекрашивания можно наблюдать в режиме реального времени, как показано на следующем рисунке.
Каждому слою соответствует свое цветовое поле. Изменится только цвет слоя, на котором происходит Repaint, а лишние слои изменят цвет, поэтому нам нужно проверить, нормально ли это.
Слишком много времени GPU обычно связано с чрезмерным использованием тяжеловесных компонентов, таких как Clip, Opacity и тени. Если вы обнаружите, что это занимает слишком много времени, вы можете обратиться к предыдущему решению для оптимизации или понижения. пожалуйста, обратитесь к разделению высокопроизводительного графического движка Liyuqian.
Профиль ЦП в нижней части рисунка 1 представляет ситуацию с затратой времени ЦП для текущего кадра, а режим «Снизу вверх» удобен для поиска наиболее трудоемкого метода.
DevTools&CPU Profiler
Рядом с производительностью находится профилировщик ЦП, который используется для подсчета времени, потребляемого ЦП в течение определенного периода времени.Как правило, судят о том, является ли бизнес ненормальным или нормальным, в зависимости от названия метода и опыта. к имени метода visitChilddren-->getScrollRenderObject и обнаружите, что мониторинг частоты кадров высокой доступности имеет проблемы с производительностью.
Devtools также имеет функциональные модули, такие как память, отладчик, сеть, журнал и т. д., которые мало используются при оптимизации беглости.Я поделюсь с вами лучшим опытом в будущем.
DebugFlags&Build
На приведенном выше рисунке показана общая таблица функций отладки для фазы сборки. Переключатель debugPrintRebuildDirtyWidgets выводит на консоль то дерево, которое в данный момент перестраивается. Функция debugProfileBuildsEnabled аналогична функции Track Widget Builds of Performance, отслеживая детали функции сборки. . Первые 3 поля используются в режиме отладки, а последнее можно использовать в режиме профиля.
DebugFlag&Paint
На приведенном выше рисунке представлена общая таблица функций отладки для этапа Paint. Функцию debugDumpLayerTree() можно использовать для печати дерева слоев, функция debugPaintLayerBordersEnabled может формировать рамку (рамку) вокруг каждого слоя, функция debugRepaintRainbowEnabled аналогична функции RainBow Enable в Инспекторе, а цвет границы изменится при перерисовке слоя. Выше упоминался debugProfilePaintsEnabled, который удобен для анализа деталей функции рисования.
Перспектива
Вышеизложенное является первой фазой практики оптимизации беглости Таотэ Флаттера, а также наиболее очевидной первой фазой соматосенсорной оптимизации. Но до конечной цели взаимодействия с пользователем еще далеко. Группа студентов обеспечивает много практических занятий. Например, оптимизация беглости движка UC Hummer, компонент списка мультиплексирования Xianyu с частичным обновлением PowerScrollView, высокоточное многомерное обнаружение зависаний онлайн и офлайн, а также способы предотвращения ухудшения решений оптимизации беглости, Taote также постоянно учится и растет. Бросьте вызов пределу. На втором этапе практики, чтобы получить максимально экстремальный опыт, Taote объединит движок Hummer для глубокой оптимизации высокопроизводительных библиотек изображений, высокопроизводительных потоковых контейнеров и создаст комплексную систему мониторинга данных в автономном и онлайн-режиме. ".
использованная литература
- Тест производительности флаттера и теория:вооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооо
- Презентация Flutter в Европе:Woohoo.YouTube.com/watch?V=VV для…
- Как сложный бизнес обеспечивает высокую производительность и плавность работы Flutter:zhuanlan.zhihu.com/p/134024247
- Официальное объяснение DartTools Flutter:woohoo.YouTube.com/watch?V=Year 4…
- Глубокое понимание рендеринга графики Flutter:воооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооо
- Официальный исходный код Flutter:GitHub.com/flutter/Appendix…
Обратите внимание на общедоступный аккаунт [Alibaba Mobile Technology] WeChat, 3 практики мобильных технологий и галантерею каждую неделю, чтобы вы могли подумать!