Всем привет, меня зовут Тимур
android разработчик в платформенной команде с опытом около 5 лет, в основном в сфере ритейла и e-com.
В какой-то момент мы поняли: пока перформанс не выражен в цифрах, его невозможно защищать, улучшать и связывать с деньгами. Поэтому мы договорились о наборе метрик, начали стабильно собирать их на устройствах пользователей, и построили понятную систему: меряем → интерпретируем → действуем.
В этой статье я расскажу про важность перформанса на мобильных устройствах, исследования бизнеса о том как перформанс влияет на конверсии, GMV, а также про конкретные метрики и примеры кода как их собирать.
Присаживайтесь, наливайте чай/кофе ☕️ и приятного чтения.
Почему вообще стоит заморачиваться перформансом?
Задачи по улучшению перформанса обычно возникают в двух случаях:
1) когда руководитель/stakeholder/инвестор открывает приложение на стареньком телефоне ( респектуйте таким, они и вправду переживают за продукт, деньги на новый девайс у них точно есть )
2) когда в поддержке начинает копиться боль от пользователей
Прежде всего перед тем как пойти и сразу улучшать перформанс, необходимо понять, а как же все таки перформанс влияет на бизнес? Для ответа на этот вопрос я провел небольшой RnD и на самом деле как оказалось тема давно вышла за рамки вкусов и предпочтений. Есть вполне конкретные цифры и исследования :
-
В отчёте Akamai/SOASTA “State of Online Retail Performance” по онлайн-ритейлу показано, что пик конверсии приходится на окно примерно 1.8–2.7 секунды на мобильных устройствах. После этого конверсия резко падает.
-
Отчёт Deloitte и Google “Milliseconds Make Millions” показывает, что ускорение мобильного сайта всего на 0.1 секунды даёт заметный рост конверсии и среднего чека. Для ритейла — плюс 8.4% к конверсии и около 9% к average order value.
Milliseconds Make Millions – улучшение на 0.1 s -
Исследование Google/SOASTA “The need for mobile speed”: если время загрузки мобильной страницы растёт с 1 до 5 секунд, вероятность того, что пользователь просто уйдёт, увеличивается примерно на 90%.
Более того в ux исследованиях долгое количество лет существует одна и та же таблица
На основе этих исследований можно сделать множество выводов, делитесь своими в комментариях, будет очень интересно почитать, я же перечислю свои:
-
Есть окно где все в рамках нормы – примерно 2 секунды до появления первого контента
-
после 3+ секунд терпение быстро заканчивается и часть людей просто не доходит до следующего шага воронки
-
даже десятые доли секунды могут быть заметны на уровне GMV, если у вас большой трафик
Влияет ли перформанс на метрики?
Отвечая на вопрос , влияет ли перформанс на метрики – да влияет, особенно когда перформанс очень плохой
Какие метрики имеет смысл собирать в мобилке
Начиная изучать вопрос, можно легко утонуть в десятке разных метрик. Чтобы этого на старте не произошло с вами я решил написать эту статью.
В процессе изучения вопроса я хотел чтобы появилась система непрерывного контроля улучшений и мониторинга метрик в которую могут смотреть как разработчики, так и лиды и продукты. Без этой системы каждый шаг будет пальцем в небо, ибо мы не сможем отслеживать улучшений в прогрессии или, не дай бог, регрессии :)
If you cannot measure it, you cannot improve it @Lord Calvin
Для этого пришлось собрать кастомный SDK который собирает эти метрики и прикрутить grafana дашборды с алертами для мониторинга деградаций. Я прошел несколько видоизменений и итераций, и для экономии вашего времени и сил расскажу о метриках, которые оказались реально полезными.
App Startup Time: время запуска приложения

Самое очевидное и самое больное место — запуск приложения. Технически запуск делится на две части:
-
Cold start: приложение выгружено из памяти, пользователь тапает по иконке
-
Warm start: приложение где-то в памяти, и мы возвращаемся из фона
Эти данные можно легко собрать автоматически, используя Firebase Performance, но для меня те цифры, которые я видел в консоли Firebase казались черной коробкой (black box), так как я не понимал что именно он считает за готовность экрана.
Также есть вариант через профайлер в android studio. Это удобно как истина на один запуск, помогает понять, где вода, а где реально тяжёлые участки. Но профайлер не расскажет, как приложение ведёт себя у тысяч пользователей на разных девайсах.
Поэтому решил написать свое решение, которое считает время от старта до первого появившегося экрана, не считая сплэш экран.
Мне было важно понимать что я сам явно контролирую откуда и до чего измеряю. [звучит двусмысленно :)]
И так делюсь с вами кодом, он выполняет несколько функций:
-
отличает Cold и Warm старт
-
меряет время до первого реально показанного экрана, а не до splash’а
-
шлёт событие в аналитику (тип старта, время и имя экрана)
object AppStartupTracker :
Application.ActivityLifecycleCallbacks,
FragmentManager.FragmentLifecycleCallbacks(),
DefaultLifecycleObserver {
enum class StartType { Cold, Warm }
private var processStartUptimeMs: Long = 0L
private var coldBaselineUptimeMs: Long? = null
private var warmBaselineUptimeMs: Long? = null
private var firstInteractiveLogged = false
private var pendingTypeForNextInteractive: StartType? = null
fun init(app: Application) {
processStartUptimeMs = getProcessStartUptimeMsFallbackAware()
coldBaselineUptimeMs = SystemClock.uptimeMillis()
app.registerActivityLifecycleCallbacks(this)
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
override fun onActivityCreated(activity: Activity, state: Bundle?) {
if (isFromLauncher(activity)) {
// Первый запуск из лаунчера → Cold, дальше → Warm
if (coldBaselineUptimeMs == null) {
coldBaselineUptimeMs = SystemClock.uptimeMillis()
}
pendingTypeForNextInteractive =
if (!firstInteractiveLogged) StartType.Cold else StartType.Warm
}
if (activity is FragmentActivity) {
activity.supportFragmentManager
.registerFragmentLifecycleCallbacks(this, true)
}
}
override fun onFragmentResumed(fm: FragmentManager, fragment: Fragment) {
val type = pendingTypeForNextInteractive ?: return
if (!isDeviceInteractiveAndUnlocked(fragment)) return
val baseline = when (type) {
StartType.Cold -> coldBaselineUptimeMs ?: processStartUptimeMs
StartType.Warm -> warmBaselineUptimeMs ?: SystemClock.uptimeMillis()
}
val startupMs = (SystemClock.uptimeMillis() - baseline).coerceAtLeast(0L)
sendStartupEvent(
type = type,
timeMs = startupMs,
fragmentName = fragment::class.java.simpleName,
)
if (type == StartType.Cold && !firstInteractiveLogged) {
firstInteractiveLogged = true
}
pendingTypeForNextInteractive = null
}
private fun sendStartupEvent(type: StartType, timeMs: Long, fragmentName: String) {
// логика отправки ивентов
}
// isFromLauncher(), isDeviceInteractiveAndUnlocked(), getProcessStartUptimeMsFallbackAware() — хелперы ниже
}
Идея простая:
-
при старте процесса запоминаем baseline
-
когда активити создана из лаунчера, помечаем, что следующий экран будет Cold или Warm стартом
-
как только первый Fragment дошёл до onResumed, а девайс уже включён и разблокирован, считаем дельту от baseline и шлём событие в аналитику
Screen Load Time: время до первого кадра с полезными данными

Одна из самых главных метрик – время загрузки конкретного экрана от открытия до появления полезного контента. Тут важно не просто держать одну цифру, а разложить её на два этапа:
|
До получения данных |
После получения данных |
|
пока мы ждём сеть, базу, маппинг, подготовку стейта |
пока UI успевает всё это отрисовать |
Я для себя использую следующую терминологию:
|
BeforeDataBecameReadyTime |
от момента, когда экран стартовал, до момента, когда данные пришли с сети/кэша и готовы к отрисовке |
|
DataRenderTime |
от получения данных до момента где пользователь действительно видит эти данные |
|
ScreenLoadTime |
сумма двух этапов |
Это разделение важно чтобы быстро понимать нам сейчас оптимизировать бекенд/сеть или разбираться с тяжелым UI-деревом
Спойлер
Ваша первичная цель по анализу метрик будет всегда одна – быстро понять где именно происходит деградация. Это UI или backend, или же конкретное устройство
Мы решили собирать эту метрику автоматически на уровне нашей архитектуры. Так как у нас готовый MVI со стейтами, редюсерами и так далее, то встроить сбор метрик не составило большого труда, я поделился концепцией ниже.
Идея в том, чтобы каждый разработчик, наследуясь от нашей BaseViewModel, переопределял условие dataFromNetworkReadyCondition
abstract val dataFromNetworkReadyCondition: DataFromNetworkReadyCondition
protected fun dataReadyWhen(predicate: (ViewState) -> Boolean): DataFromNetworkReadyCondition =
DataFromNetworkReadyCondition.FlowFromNetworkReady(
_viewState.map(predicate).distinctUntilChanged()
)
потом во view (у меня compose) подписываемся на этот flow
LaunchedEffect(dataFromNetworkReadyCondition) {
when (dataFromNetworkReadyCondition) {
DataFromNetworkReadyCondition.NoRequiredNetworkQueries -> Unit
is DataFromNetworkReadyCondition.FlowFromNetworkReady -> {
dataFromNetworkReadyCondition.flow
.distinctUntilChanged()
.first { it }
val beforeDataBecameReadyTime = deltaMs(composableStartTime)
// Choreographer здесь поможет посчитать время до следующего кадра после готовности данных
choreographer.postFrameCallback {
val dataRenderTime = deltaMs(dataReadyNs)
val screenLoadTime = waitDataMs + renderAfterDataIsReadyMs
}
}
}
}
Варианты DataFromNetworkReadyCondition, его можно расширять по вашим нуждам, например если данные не из сети, а из кэша
sealed interface DataFromNetworkReadyCondition {
/** На экране нет стадии загрузки данных. */
data object NoRequiredNetworkQueries : DataFromNetworkReadyCondition
/** На экране загрузка из сети */
data class FlowFromNetworkReady(val flow: kotlinx.coroutines.flow.Flow<Boolean>) : DataFromNetworkReadyCondition
}
Логика проста:
ждем выполнение этого условия -> считаем дельту от запуска экрана -> отправляем в аналитику
Плавность UI: Hitch / Jank rate

Следующая, но не по важности метрика – плавность UI
Пользователь не сидит с секундомером, считая секунды. Он либо чувствует, что листать приятно, либо приложение дёргается и подвисает
Это описывает метрика – Hitch rate (по сути то же, что slow/janky frames в Android Vitals):
-
считаем количество кадров, которые заняли больше порога
-
делим на общее число кадров за сессию экрана → получаем процент.
Время порога одного кадра в миллисекундах считается так:
где f — частота обновления (Hz)
Пример для 60 Hz:
Пример для 120 Hz:
В сети нету конкретных четких понятий для определения SLA по Hitch Rate. Поэтому предлагаю вам ориентироваться под свой продукт.
Также важно понимать что помимо janky frames, есть еще метрика frozen frames – они в купе создают общую картину по hitch rate.
⚠️ Hitch Rate актуален для экранов, где много кадров, например скролл, анимации и тд. Если у вас статичный экран с несколькими кадрами, ориентироваться на эту метрики для такого рода экранов не стоит. ⚠️
И так пример как можно составить SLA по Hitch rate:
-
до 5% — большинство людей вряд ли заметят
-
5–10% — субъективно местами подлагивает
-
10% + — на массовых экранах это уже прям заметная боль
Советую не забывать, что все зависит от типа класса устройств. На флагманах будут совсем другие данные, нежели на слабеньких дешевых android устройствах. В ваших дашбордах необходимо делить эти данные по классам устройств. Об этом расскажу в следующих пунктах
Для сбора hitch rate есть готовая библиотека от google -JankStats.
Псевдокод с примером:
import androidx.metrics.performance.JankStats
val jankFramesCount = 0
val jankStats = JankStats.createAndTrack(window) { frame ->
if (frame.isJank) jankFramesCount++
}
Сеть: затраченное время на запрос
Во многих компаниях у бэкенд-команд есть метрики: как быстро отвечает сервер и сколько времени запрос проходит через API Gateway.
Но пользовательский опыт зависит не только от сервера. У пользователей разный интернет, разные устройства, разные условия в разных странах. И бизнесу важно понимать не “сколько занял запрос на сервере”, а сколько времени прошло до момента, когда пользователь реально получил данные на экране. Эти данные помогают не только искать проблемы, но и рождают бизнес-гипотезы: где добавить кэш, где упростить payload, где поменять стратегию ретраев.
Например, сервер может отвечать за 100 мс, но на устройстве пользователь увидит данные только через 1.5 с. Скорее всего, узкое место — сеть/ретраи/медленный девайс, значит логично рассмотреть кэширование и оптимизации клиента.
Поэтому полезно собирать end-to-end метрику времени запроса на клиенте, которая включает этапы: подготовка и маппинг запроса, сеть, ретраи, парсинг ответа и т. д.
Можно кластеризовать запросы по времени и посчитать, сколько трафика проходит через каждый кластер:
|
до 0.8s |
ощущается как мгновенно |
|
0.8–2s |
верх комфортной зоны |
|
2–3s |
уже подвисает |
|
3+ s |
высока вероятность что пользователь просто уйдет |
Такой срез даёт бизнесу не просто “топ медленных запросов”, а общую картину нагрузки: видно, какая часть трафика живёт в быстрых диапазонах времени ответа, какая застряла в зоне 2–5 секунд, а какая стабильно уезжает за 5+ секунд. По одному графику можно понять, где на самом деле теряется скорость и какие запросы стоит оптимизировать в первую очередь, чтобы это дало заметный эффект по всей воронке юзера.

Окружение: батарея, CPU, RAM, device tiers
Отдельный блок, который, как мне кажется, многие недооценивают это контекст устройства. Одно и то же время загрузки или тот же hitch rate чувствуется совершенно по-разному на флагмане и на старом телефоне с 1 ГБ памяти.
Поэтому вместе с перформанс-метриками я стараюсь всегда собирать окружение:
-
объём RAM (объём памяти, который ест процесс)
-
использование CPU
-
частоту экрана (refresh rate в Hz)
-
уровень батареи
Device Tier (класс устройства)
Поверх всех метрик я делю девайсы на device tiers -> условное разбиение пользователей на слабый / средний / мощный.
Зачем вообще это нужно, пара типичны�� ситуаций:
-
У разработчиков топовые девайсы, на них всё летает. В Grafana 90 перцентиль ScreenLoadTime вроде норм. А потом открываешь срез только по low-tier устройствам, и там всё красное
-
Пользователь пишет в поддержку: “Приложение тормозит и жрёт батарею”. Без метрик по батарее/CPU это превращается в поиск иголки в стоге сена. С метриками можно честно ответить:
-
да, у нас на устройствах с 3 ГБ RAM и 60 Гц есть проблемы на таких-то экранах
-
или наоборот — по данным, наше приложение за сессию съедает X%, остальное уходит на фоновые процессы
-
По суть окружение это способ понять, где на самом деле болит, либо у всей аудитории, либо у конкретного класса устройств.
Делить по device tier можно как угодно, я использую три параметра (cpu, ram, screen Hz )
На дашбордах я обязательно делаю отдельные графики по каждому tier’у.
Очень отрезвляет, когда видишь, что, например:
-
на мощных-tier всё зелёное
-
на средних — терпимо
-
а на слабых-tier тот же экран превращается в болото
Батарея, CPU и RAM: зачем смотреть отдельно?
-
CPU / active rendering time
-
Если у экрана нормальный ScreenLoadTime, но при этом сессия грузит CPU на 70–80% и гоняет кучу кадров — это сигнал, что UI делает что-то очень тяжёлое (например, лишние анимации, бесконечные recomposition’ы и т.д.)
-
Мы например так обнаружили проблемы в нашей архитектуре
-
-
ОЗУ (RAM)
-
Можно видеть, как растёт память во время сессии экрана. Это помогает ловить утечки и тяжелые списки/изображения, которые постепенно раздувают процесс
-
-
Батарея
-
Я обычно логирую уровень заряда на момент сессии. Можно, например, выделить пользователей с низким зарядом и посмотреть, не ведёт ли себя приложение у них хуже (дополнительные ограничения системы, агрессивный Doze, и т.д.)
-
Также полезно трекать батарею до захода на твой экран и после выхода, если это обьединить со временем сессии на твоем экране можно будет понять насколько быстро твой экран сжигает батарею
-
Эти метрики по окружению не обязательно выносить на первый экран дашборда, но для глубокого анализа они необходимы. На графиках это может выглядить примерно вот так:
В моем случае все экраны на Jetpack Compose, поэтому код достаточно простой:
-
при входе на экран запоминаю:
-
время старта сессии
-
текущее CPU-время процесса
-
-
при onDispose экрана считаю:
-
длительность сессии
-
сколько CPU мы сожгли за это время
-
какой был уровень батареи
-
сколько памяти занимал процесс
-
-
одним событием отправляю это в аналитику
@Composable
fun TracedScreen(
screenName: String,
content: @Composable () -> Unit,
) {
val context = LocalContext.current
// время начала сессии экрана
val startNs = remember { System.nanoTime() }
// CPU-время процесса на старте
val cpuStartMs = remember { Process.getElapsedCpuTime() }
DisposableEffect(Unit) {
onDispose {
val sessionMs = ((System.nanoTime() - startNs) / 1_000_000)
.coerceAtLeast(0L)
// разница CPU-времени процесса за сессию
val cpuEndMs = Process.getElapsedCpuTime()
val cpuDeltaMs = (cpuEndMs - cpuStartMs).coerceAtLeast(0L)
val cores = Runtime.getRuntime()
.availableProcessors()
.coerceAtLeast(1)
// грубая оценка CPU% за сессию
val cpuUsagePct: Double? = if (sessionMs > 0) {
((cpuDeltaMs.toDouble() / (sessionMs * cores)) * 100.0)
.coerceIn(0.0, 100.0)
} else null
val battery = context.batteryLevel() // 0–100, свой extension
val pssMb = context.processPssMb() // MB, свой extension
sendEnvMetrics(
screenName = screenName,
sessionMs = sessionMs,
cpuUsagePct = cpuUsagePct,
batteryLevel = battery,
memoryMb = pssMb,
)
}
}
Box { content() }
}
First Frame Render Time (FFRT): когда появился первый кадр
Если App Startup Time отвечает на вопрос через сколько приложение стало интерактивным?, то First Frame Render Time это про момент, когда пользователь перестал смотреть в пустой экран.
Почему это важно отдельно от ScreenLoadTime:
-
Психологически первое появление хоть какого-то UI очень сильно снижает ощущение что приложение зависло
-
даже если данные ещё едут, быстрый FFRT даёт чувство отзывчивости
Как я уже говорил в моем случае все экраны на Compose, поэтому я делаю простой трюк:
-
Запоминаю время в момент первой композиции.
-
Вешаю Choreographer.FrameCallback, который вызовется при отрисовке первого кадра
-
В этом коллбэке считаю дельту и отправляю событие в аналитику.
Упрощенно обертка над compose выглядит так:
@Composable
fun TracedScreen(
screenName: String,
content: @Composable () -> Unit
) {
val startNs = remember { System.nanoTime() }
val choreographer = remember { Choreographer.getInstance() }
// Логируем время до первого кадра
DisposableEffect(Unit) {
val callback = Choreographer.FrameCallback {
val firstFrameMs = (System.nanoTime() - startNs) / 1_000_000
sendFirstFrameEvent(screenName, firstFrameMs)
}
choreographer.postFrameCallback(callback)
onDispose {
choreographer.removeFrameCallback(callback)
}
}
Box {
content()
}
}
private fun sendFirstFrameEvent(screenName: String, timeMs: Long) {
// отправка в аналитику
}
UX Index: сводная метрика
Представь, что у нас уже есть куча метрик: App Startup Time, ScreenLoadTime, HitchRate, сеть, ошибки и т.д.
Для разработчика это окей, а вот для продакта или руководителя – уже куча графиков. Хочется иметь одну сводную оценку, чтобы быстро понять:
-
у какого экрана UX в целом хуже
-
стало лучше или хуже после релиза
-
где копать глубже
Отсюда и появляется UX Index – это сводный балл качества UX экрана (или приложения в целом) по шкале от 0 до 100:
-
90–100 отлично, всё в зелёной зоне
-
70–90 нормально, но есть куда ускоряться
-
ниже 70 заметно больно, стоит разбираться
Он не заменяет отдельные метрики, а работает как верхнеуровневая лампочка: одна цифра, по которой можно сравнить экраны между собой и смотреть тренды по версиям.
Внутри UX Index не магия, а смесь знакомых вещей, ScreenLoadTime + Hitch Rate + App Startup Time, при желании можно добавить ещё кусочек сетевых задержек или ошибок, если это больное место.
Считаем что-то вроде взвешенного среднего:
UX_INDEX = 0.2 * score(ScreenLoadTime) +
0.2 * score(HitchRate) +
0.2 * score(AppStartup) +
0.2 * score(NetworkRequestTime) +
0.2 * score(FirstFrameRenderTime)
// Абстрактный пример, формулу можете усложнять в зависимости от своих метрик
Как принимать решения на основе этих метрик?
И так мы начали собирать все эти метрики, сделали красивый дашборд. Но этого обычно мало, нужно на языке бизнеса научиться рассказыват про перформанс.
Для этого нужно в первую очередь надо честно ответить себе на два вопроса:
-
Как это помогает бизнесу принимать решения?
-
Как это встраивается в регулярные процессы разработки, а не живёт отдельной жизнью?
Бизнесу неинтересно, что у вас ScreenLoadTime равен например ±2c, тут скорее про:
сколько людей дошли до следующего шага
сколько из них купили
сколько денег вы теряете на каждом “лишнем” интервале ожидания
Самый простой практичный шаг это связать перформанс с основной воронкой.
Возьмите ваш стандартный путь пользователя, например, список → товар → корзина → оплата. Для каждого шага у нас теперь есть технические метрики и бизнес метрики. Дальше делаем очень приземлённую вещь:
-
делите сессии на “быстрые” и “медленные” (например, < 2 секунд и > 3 секунд до контента)
-
считаете конверсию отдельно по каждой группе
В большинстве случаях разница видна – быстрые сессии чаще доходят до конца воронки, медленные — чаще от��аливаются
Да, это не чистый A/B-тест, там куча факторов, но это уже не разговор уровня что мне кажется, а уже конкретный срез даннных по типу:
При загрузке каталога до 2 секунд конверсия в добавление в корзину на X% выше, чем при 3+ секунд
И вот такой график бизнес уже смотрит совсем по-другому
A/B-тесты для технических изменений
Самый простой способ (если у вас уже есть A/B тесты в компании) это провести такой тест и показать пользу технических улучшений.
А еще проще тестово замедлить один из экранов и посмотреть как поменяется конверсия. ( 🚨 Делать на свой страх и риск 🚨)
Но часто бывает так что, вы например ускорили экран закэшировали данные, уменьшили ScreenLoadTime, запускаете А/B, а в результатах серые метрики, ничего не прокрасилось, вывод = скорость ни на что не влияет
На практике чаще всего проблема в нескольких местах:
-
метрика эксперимента выбрана так, что она слишком шумная для этого эффекта (например, общий GMV по всем пользователям за две недели)
-
или трафика теста не хватает, чтобы поймать дельту на уровне десятых долей процента
-
или куча похожих подводных камней которые отличают технический A/B тест от продуктового
Для того чтобы это завелось, необходимо договориться с аналитиками о наборе технических метрик для A/B-тестов и зафиксировать процесс: как заводятся такие эксперименты, кто помогает с дизайном/метриками
Как обернуть всё это в процесс?
Дальше начинается то, чем должен заниматься человек/команда уровня senior/staff: не просто мерять, а завести вокруг этого рутину – систему непрерывных улучшений.
1. Один живой дашборд, а не двадцать
Сначала нужен один основной дашборд, а не музей метрик.
В нём обычно достаточно:
-
таблицы ключевых экранов: трафик, UX Index, ScreenLoadTime, HitchRate
-
фильтров по версии и device tier
-
пары панелей по сетевым запросам: распределение по времени и доле трафика
Этим дашбордом вы реально будете пользоваться на встречах. Остальное можно держать в технических дашбордах для глубокой отладки.
2. Ежемесячный performance-review
Это не тот performance review о котором вы подумали ))))
Хороший формат — регулярная встреча раз в месяц, где собираются: performance-менеджер. по одному человеку от мобильных команд, backend и если нужно QA / аналитики.
На этой встрече происходят три простые вещи:
-
Смотрят, какие экраны в красной зоне по SLA
-
Определяют топ-3–5 проблем по продуктовой ценности: трафик × боль по перформансу
-
Переводят это в задачи: у каждой проблемы есть владелец, дедлайн
Цель не в том, чтобы всё починить за один созвон, а в том, чтобы перформанс был регулярной темой, как баги или инциденты
3. Распределение ролей
Также важно распределить роли, иначе эта инициатива одного человека умрет через квартал
Примерная схема:
|
Платформа |
Поддерживает SDK, метрики, дашборды, алерты, общие компоненты и архитектурные гайдлайны. То есть создаёт среду, где делать быстрый экран проще, чем медленный. |
|
feature команды |
Отвечают за перформанс своих экранов и API. Смотрят на дашборды после в��пуска релиза и планируют перформанс работы как часть обычного roadmap’а. |
|
EM / Тимлиды |
Договариваются, что перформанс — это часть качества продукта, т.е выделяют ресурсы и приоритизациюог |
✅ Итог
Спасибо что дошли до этого блока, надеюсь статья была полезна, буду благодарен если оставите голос :)
От меня небольшая шпаргалка по общему процессу интеграции работы с перформансом в компанию
-
Начните с измерения: App Startup, FFRT, ScreenLoadTime, HitchRate, пара сетевых метрик и окружение
-
Свяжите это с воронкой: быстрые vs медленные сессии и их конверсия
-
Сделайте один основной дашборд: экраны, версии, device tiers, UX Index
-
Заведите регулярный performance-review: раз в месяц, с задачами, владельцами и сроками
-
Встройте performance budget в разработку: ключевые экраны получают свои лимиты по времени и плавности
-
Зафиксируйте роли: кто отвечает за инструменты, кто за экраны, кто даёт приоритеты
Дальше можно углубляться: добавлять AB-тесты для технических изменений, усложнять модель UX Index, строить более умные алерты. Но базовый каркас везде примерно один и тот же: меряем → переводим на язык денег → встраиваем в процессы.
Автор: timkaopensoul


