Как отследить и измерить лаги в UI помимо визуального восприятия
Что проверяют
Умеете ли вы превратить «тормозит» в число и найти причину конкретного медленного кадра. Интервьюер ждёт, что вы назовёте метрики (доля медленных кадров, перцентили времени кадра) и инструменты как для локальной отладки, так и для продакшена. Следом обычно спрашивают, как ловить регрессии в CI.
Как отвечать
Сначала бюджет: на 60 Гц кадр должен уложиться в 16,7 мс, на 90 Гц в 11,1 мс, на 120 Гц в 8,3 мс. Дальше инструменты по уровням:
- быстрая оценка:
adb shell dumpsys gfxinfo <package>показывает число кадров, долю janky frames и перцентили времени кадра; перед сценарием статистику сбрасывают командойdumpsys gfxinfo <package> reset; - поиск причины: System Trace в Android Studio Profiler или Perfetto. Видно, что делали главный поток и RenderThread в конкретном кадре, а с Android 12 FrameTimeline показывает ожидаемое и фактическое время каждого кадра. Свои участки размечают через
trace("loadFeed") { }изandroidx.tracing; - регрессии в CI: Jetpack Macrobenchmark с
FrameTimingMetricпрогоняет сценарий на реальном устройстве и выдаётframeDurationCpuMsиframeOverrunMsпо перцентилям; - продакшен: библиотека JankStats из
androidx.metricsсообщает о медленных кадрах вместе с состоянием экрана, а Android vitals в Google Play показывает slow rendering, frozen frames (дольше 700 мс) и ANR; - профилактика:
StrictModeловит диск и сеть на главном потоке, для Compose Layout Inspector показывает число рекомпозиций.
Choreographer.postFrameCallback для подсчёта интервалов между кадрами годится как самодельный индикатор, но причину он не покажет.
Где спотыкаются
Меряют на debug-сборке. Без R8 и Baseline Profiles и с включённой отладкой Compose заметно медленнее, поэтому цифры снимают на release или profileable сборке.
Смотрят средний FPS. Десять кадров по 200 мс на фоне тысячи быстрых почти не двигают среднее, а пользователь видит именно их.
Берут не те инструменты. Traceview давно устарел, а инструментирующая трассировка методов сама искажает время, для замеров нужен сэмплинг. LeakCanary ищет утечки памяти, а не лаги, хотя утечки и частый GC тоже дают подёргивания.