
Главное
• В 2026 году производительность Compose по-прежнему реальный риск для продакшена. Неправильная работа со state, лямбдами и нестабильными типами до сих пор выводит в релиз приложения, которые работают на 3,5 FPS даже на флагманском железе — кадр рендерится 450 мс при бюджете в 16 мс.
• Vkompose — самая жёсткая линия обороны. Этот open-source-набор от VK.com включает плагин для IntelliJ, плагин для Gradle и правила Detekt, которые подсвечивают, логируют и блокируют проблемы с рекомпозицией ещё на этапе компиляции, а не только в рантайме.
• Strong Skipping Mode бесплатно закрывает около 30% проблем. Compose Compiler 1.5.4+ пропускает рекомпозицию у composable-функций, чьи параметры равны по ссылке, даже если формально они нестабильны — включите этот режим прежде всего остального.
• Многослойная защита эффективнее одного инструмента. Соберите вместе Strong Skipping + Vkompose + Detekt + Layout Inspector + Baseline Profiles + Macrobenchmark — каждый ловит свой класс деградаций, а CI/CD связывает их в единый контур.
• Зрелые команды после миграции выпускают релизы быстрее. Twitter сократил объём UI-шаблонов в 10×, Reddit выпустил Recap на Compose, профиль optimize в R8 убирает около 30% времени холодного старта. Переход окупается, если дисциплина по производительности уже выстроена.
Зачем Фора Софт написала это руководство
Фора Софт выпускает Android-приложения уже более 17 лет. Около 40% нашей активной инженерной команды занято мобильными, видео- и real-time-продуктами, и многие из них последние три года живут на Jetpack Compose. Мы наткнулись на каждую ловушку рекомпозиции из списка ниже, починили их в продакшене и зафиксировали эту дисциплину в наших внутренних проверках CI/CD.
Vkompose — не наш проект, это open source от Android-команды VK.com, — но мы используем его на большинстве проектов с активным Compose, потому что ни один другой набор инструментов не даёт такой же комбинации блокировки на этапе компиляции, подсветки прямо в IDE и логирования рекомпозиций в рантайме в одном пакете. Эта статья — то самое практическое руководство, которое мы вручаем нашим Android-инженерам при входе в Compose-проект, вместе с более широким набором инструментов для производительности (Strong Skipping, Modifier.Node, Baseline Profiles, оптимизация R8), благодаря которому Vkompose начинает окупаться.
Если вы оцениваете или проводите аудит Android-продукта на Compose — будь вы CTO, которого беспокоят подтормаживания, продакт-оунер, отстаивающий дедлайн запуска, или основатель, выбирающий партнёра для выпуска первой версии, — это руководство в точности то, что мы разобрали бы с вами на созвоне. На каждом проекте мы применяем подход Agent Engineering, чтобы сжать сроки и стоимость; именно поэтому наши оценки обычно оказываются ниже среднего по рынку.
Compose-приложение подтормаживает?
Закажите 30-минутный разбор производительности Compose с нашими Android-лидами — мы просканируем кодовую базу на главные ловушки рекомпозиции и дадим конкретный план исправлений.
Почему производительность Compose всё ещё болит в 2026 году
Jetpack Compose стал UI-инструментом Android по умолчанию и языком, на котором говорит каждая современная Android-команда: один только январский релиз Google 2024 года дал примерно +20% к FPS при скролле и +12% к скорости запуска. Платформа становится всё быстрее. Приложения — всё медленнее.
Причина в том, что декларативная модель Compose меняет полный контроль на удобную работу со state — а удобной работой со state легко пользоваться неправильно. В задокументированных продакшен-кейсах ленты на Compose работали на 3,5 FPS (450 мс на кадр) на флагманских устройствах из-за одного нестабильного параметра List, который вызывал 47 рекомпозиций на каждый жест прокрутки. Ничего из этого не всплывает на код-ревью — это видно только в Layout Inspector или в жалобах пользователей.
Решение — не героическая оптимизация. Это многослойная защита: Strong Skipping Mode, Vkompose для проверок на этапе компиляции и в рантайме, правила Detekt для покрытия code smells, Layout Inspector для точечной отладки, Baseline Profiles для AOT-компиляции и режим R8 Full для всего остального. Каждый инструмент ловит свой класс деградаций. Собранные вместе, они переводят продакшен-команду Android из состояния «надеемся, что плавно» в «CI/CD блокирует мерж, если он тормозит».
Семь ловушек рекомпозиции, в которые попадает каждая Compose-команда
Если вы проводите аудит кодовой базы на Compose, в первую очередь ищите эти семь паттернов — на них приходится примерно 90% нашей работы по исправлениям.
1. Нестабильные типы в параметрах. Коллекции (List, Set, Map) для компилятора Compose всегда нестабильны. Data-классы нестабильны, если хотя бы одно их свойство нестабильно. Модели из других модулей нестабильны, если модуль-источник собран без Compose. Аннотируйте через @Stable/@Immutable, переходите на ImmutableList из Kotlinx-Immutable или используйте файл конфигурации стабильности.
2. Лямбды, захваченные в нестабильной области видимости. Inline-лямбды, выделяемые заново при каждой рекомпозиции, заставляют рекомпозироваться каждого ребёнка, который их принимает. Передавайте ссылки на методы (::onClick) или используйте remember { { … } } ради стабильной идентичности.
3. Слишком широкая область рекомпозиции. Чтение state не на том уровне инвалидирует всё поддерево. Опускайте чтение state до самой мелкой листовой composable-функции, которой оно нужно; передавайте лямбды вместо значений, когда листовому узлу нужно изменить state.
4. Отсутствие ключей в LazyColumn/LazyRow. Без стабильных ключей Compose воспринимает любую перестановку элементов как новый элемент, выбрасывает запомненный state и запускает функцию заново. Всегда передавайте key = { it.id }.
5. Побочные эффекты в теле composable-функции. Запросы к БД, файловый ввод-вывод, парсинг JSON внутри composable выполняются при каждой рекомпозиции. Оборачивайте их в remember { … } или LaunchedEffect.
6. Неправильное использование derivedStateOf. Применять его там, где хватило бы обычного значения, — лишние накладные расходы; не применять там, где он нужен, — запускать каскад рекомпозиций. Берите его, когда производное значение зависит от нескольких источников state, но не должно пересчитываться при каждом их изменении.
7. Modifier.composed вместо Modifier.Node. Фабрика composed пересобирает модификаторы при каждой рекомпозиции; API Node переживает их. Перевод критичных к производительности кастомных модификаторов даёт ускорение в 3×–10× на бенчмарк-микротестах.
Заказывайте внешний аудит кода, когда: команда может перечислить симптомы (подтормаживания, ANR, рывки при скролле), но не может назвать причину, либо когда кодовая база старше Strong Skipping (Compose Compiler < 1.5.4). Наше руководство по аудиту кода описывает диагностический процесс, который мы проводим.
Прочитайте отчёты компилятора прежде, чем писать исправления
Компилятор Compose может выдавать два текстовых отчёта, которые точно говорят, какие классы нестабильны и какие composable-функции пропускаемы. Включите их первым делом; всё остальное — лишь гипотезы.
tasks.withType<KotlinCompile>().configureEach {
compilerOptions {
freeCompilerArgs.addAll(
"-P", "plugin:androidx.compose.compiler.plugins.kotlin:" +
"reportsDestination=${'$'}{buildDir}/compose_metrics",
"-P", "plugin:androidx.compose.compiler.plugins.kotlin:" +
"metricsDestination=${'$'}{buildDir}/compose_metrics"
)
}
}
После следующей сборки compose_metrics/<module>-classes.txt перечислит каждый класс как Stable, Immutable или Unstable; composables.txt покажет, какие функции Restartable и Skippable. Первый проход аудита — это просто прочитать их и приоритизировать экраны, чьи ключевые composable-функции не пропускаются.
Vkompose — что на самом деле делает каждый плагин
Vkompose — это набор из трёх независимо устанавливаемых инструментов для производительности Compose, который поддерживает Android-команда VK.com. Набор решает то же семейство задач, что и Layout Inspector, но с более жёсткой блокировкой, более гибким логированием и удобными для CI/CD результатами.
1. Плагин для IntelliJ IDEA / Android Studio
Подсвечивает composable-функции, которые с высокой вероятностью рекомпозируются без необходимости: отсутствующие аннотации @Stable, нестабильные параметры, неправильно помеченные composable-функции. Подсветка в IDE предупреждает на уровне объявления функции, так что джуниоры видят проблему пока пишут код, а не спустя спринт.
2. Плагин для Gradle (тот самый строгий)
Работает на этапе компиляции и роняет сборку, если в неё попадёт неоптимизированная composable-функция. Это разница между советом и принуждением. Вместе с плагином поставляется RecomposeLogger — опциональная утилита для рантайма, которая выводит, какой именно параметр изменился, когда функция рекомпозировалась.
// build.gradle.kts (module)
plugins {
id("com.vk.vkompose") version "0.5"
}
vkompose {
skippabilityCheck = true // fail build on unskippable @Composable
recompose {
isHighlighterEnabled = true // visual border around recomposing nodes
isLoggerEnabled = true // logs reason of every recomposition
}
testTagsCheck = true // require testTag in semantic UI
}
3. Правила Detekt
Правила статического анализа, встраиваемые в ваш существующий пайплайн Detekt. Они ловят отсутствующие типы параметров, нестабильные формы параметров и тот небольшой набор паттернов code smell, который проверки Vkompose на уровне компилятора намеренно пропускают.
Vkompose против Layout Inspector, Rebugger и правил Detekt
Есть как минимум четыре способа отслеживать проблемы производительности Compose. И они не взаимозаменяемы.
| Инструмент | Что ловит | Блокирует сборку? | Для чего лучше всего |
|---|---|---|---|
| Layout Inspector | Счётчики рекомпозиций/пропусков, иерархия | Нет | Точечная отладка только на эмуляторе |
| Rebugger | Причины рекомпозиции по каждому компоненту | Нет | Лёгкая трассировка по ходу дела |
| Правила Detekt для Compose | Паттерны code smell (переиспользование Modifier, именование параметров) | Да (порог Detekt) | Единообразие стиля в CI |
| Vkompose | Ошибки стабильности, непропускаемые composable-функции, причины рекомпозиций в рантайме | Да (плагин Gradle) | Продакшен-уровень принуждения + отладка вживую |
Берите Vkompose, когда: у вас Compose-кодовая база больше ~50 экранов, пайплайн CI/CD должен отклонять деградации производительности, а Android-команда достаточно большая, чтобы ручная отладка в рантайме перестала масштабироваться. Для хобби-приложения на 1–2 человека Layout Inspector + отчёты компилятора обычно достаточно.
Strong Skipping Mode — самые дешёвые 30% выигрыша
Compose Compiler 1.5.4 представил Strong Skipping Mode, а версия 2.0+ перевела его в статус готового к продакшену. С включённым Strong Skipping composable-функции, чьи нестабильные параметры равны по ссылке (===), пропускаются вместо постоянного перезапуска — даже если сам тип параметра формально нестабилен.
// build.gradle.kts
android {
composeOptions {
enableStrongSkippingMode = true
}
}
Внутренние бенчмарки — и Google, и те, что мы прогоняли на клиентских кодовых базах, — показывают, что около 30% проблем рекомпозиции исчезают без единого изменения в коде, как только включается Strong Skipping. Это к тому же самая дешёвая и быстрая мера в наборе. Включите её прежде, чем начнёте расставлять аннотации @Stable.
Нужен аудит производительности Compose?
Наши Android-лиды прогонят по вашей кодовой базе Vkompose, Layout Inspector, Macrobenchmark и отчёты компилятора — вы получите список задач с оценками трудозатрат за 7–10 дней.
Layout Inspector — для бага, который вы уже умеете воспроизвести
Как только экран начинает подтормаживать на реальном взаимодействии, Layout Inspector — самый быстрый способ найти виновную composable-функцию. Откройте Tools → Layout Inspector, подключитесь к своей debug-сборке и включите «Show Recomposition Counts» в настройках дерева компонентов.
У каждого узла появляются два столбца: Recompose (сколько раз функция запускалась) и Skip (сколько раз Compose решил её пропустить). Высокое соотношение Recompose к Skip — особенно под интерактивной нагрузкой — это улика. Layout Inspector входит в Android Studio, поэтому он точка старта по умолчанию; рантайм-подсветка Vkompose дополняет его на физических устройствах.
Baseline Profiles и Macrobenchmark — как мы это доказываем
Оценка FPS на глаз не выживает в CI-пайплайне. Выживает связка Baseline Profiles + Macrobenchmark: поставляйте предварительно скомпилированные «горячие» пути, чтобы сократить холодный старт примерно на 30%, а затем измеряйте задержку кадра по P95 в воспроизводимом тесте.
// :baseline-profile module
@RunWith(AndroidJUnit4::class)
class FeedScrollBenchmark {
@get:Rule val rule = MacrobenchmarkRule()
@Test fun feedScrollFrames() = rule.measureRepeated(
packageName = "com.example.app",
metrics = listOf(FrameTimingMetric()),
iterations = 10,
startupMode = StartupMode.COLD
) {
pressHome()
startActivityAndWait()
device.findObject(By.res("feed")).fling(Direction.DOWN)
}
}
Запускайте его по ночам. Роняйте пайплайн, если время кадра по P95 переползает за 16 мс. Свяжите его с генератором Baseline Profile, который записывает критичный пользовательский сценарий; именно AOT-скомпилированный результат даёт те +30% к скорости запуска, о которых говорит Google.
Переведите Modifier.composed на Modifier.Node
Modifier.composed { … } пересобирает свежий экземпляр модификатора при каждой рекомпозиции родителя, выделяя память по дороге. API Modifier.Node переживает рекомпозиции, хранит state напрямую и в бенчмарках работает в 3×–10× быстрее.
// Old — avoid
fun Modifier.brandRipple() = composed {
val state = remember { mutableStateOf(0) }
drawWithContent { /* ... */ }
}
// New — prefer
private class BrandRippleNode : Modifier.Node() {
var state = mutableStateOf(0)
// hooks here survive recompositions
}
fun Modifier.brandRipple(): Modifier =
this then BrandRippleElement
Проверьте каждый кастомный модификатор в кодовой базе. Переводите в первую очередь те, что в списках, анимациях и сложных макетах, — именно там накапливаются аллокации.
Режим R8 Full + файл конфигурации стабильности
Два изменения в конфигурации стабильно двигают метрики на 20–30% без единой правки в исходном коде.
1. Режим R8 Full. Переключите proguard-android.txt на proguard-android-optimize.txt и включите android.enableR8.fullMode=true. Google сообщает о +30% к скорости запуска и -25% к числу ANR на репрезентативных приложениях.
2. Файл конфигурации стабильности. Объявите сторонние типы, которые вы не можете изменить, стабильными в одном файле конфигурации (stability_config.conf). Compose будет считать их @Stable на этапе компиляции, не прибегая к monkey-patching зависимости.
CI/CD — превращаем набор инструментов в страховочный барьер
Набор инструментов имеет смысл только если сборка падает тогда, когда должна. Встройте Vkompose, Detekt и Macrobenchmark в пайплайн, чтобы каждый PR доказывал, что не приводит к деградации.
// .github/workflows/compose-perf.yml
name: Compose performance gate
on: [pull_request]
jobs:
perf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./gradlew detekt
- run: ./gradlew :app:assembleRelease // Vkompose Gradle plugin
- run: ./gradlew :baseline-profile:macrobenchmark
- run: ./tools/check-frame-budget.sh // fail if P95 > 16 ms
Продакшен-кейсы — что выпускают хорошо организованные Compose-команды
Twitter сократил объём UI-шаблонов примерно в 10× после полной миграции на Compose, попутно ускорив исправление багов и сделав темизацию более гибкой для A/B-тестирования. Reddit выпустил «Recap» на Compose, опираясь на его движок анимаций вместо вложенных ConstraintLayout. Square / Cash App публично взяли курс на Compose для новых поверхностей и сообщают о сопоставимом росте скорости разработки внутри компании. Январский релиз Google 2024 года один только задокументировал примерно +20% к FPS при скролле и +12% к скорости запуска — этот выигрыш каждая команда получает бесплатно при обновлении Compose Compiler.
Compose Multiplatform — где Vkompose заканчивается
Vkompose поставляется как плагин Android Gradle + правила Detekt и работает только под Android. Команды, использующие Compose Multiplatform для десктопа, iOS или Web, не получат принуждение Vkompose на этих платформах. Запланируйте отдельную стратегию профилирования: Macrobenchmark/отчёты компилятора Compose Multiplatform на iOS, Lighthouse для Compose Web, десктопный бенчмарк-стенд через JFR.
Сколько стоит починить производительность Compose — чего ожидать
Когда Фора Софт берётся за проект по аудиту и исправлениям на Compose-продукте, ниже типичный объём и сроки, которые мы озвучиваем.
| Проект | Что входит | Ориентировочный диапазон | Сроки |
|---|---|---|---|
| Аудит производительности Compose | Отчёты компилятора, прогон Vkompose, трассировки Layout Inspector, приоритизированный список задач | 450 тыс.–900 тыс. ₽ | 7–10 дней |
| Исправления уровня Tier-1 | Strong Skipping, ключи в параметрах, чистка захвата лямбд, режим R8 Full | 750 тыс.–1,8 млн ₽ | 2–3 недели |
| Рефакторинг уровня Tier-2 | Перепроектирование формы state, чистка derivedStateOf, миграция на Modifier.Node | 1,8–4,5 млн ₽ | 4–8 недель |
| Укрепление CI/CD | Плагин Vkompose для Gradle, правила Detekt, Macrobenchmark в CI, бюджеты производительности | 600 тыс.–1,1 млн ₽ | 1–2 недели |
Схема принятия решения — выберите план производительности Compose за пять вопросов
1. На какой версии Compose Compiler вы сидите? Ниже 1.5.4 → сначала обновитесь; одно это разблокирует Strong Skipping. Выше 2.0 → вам доступен весь набор инструментов.
2. Сколько экранов? Меньше ~20 → отчётов компилятора + Layout Inspector достаточно. Больше 50 → ставьте плагин Vkompose для Gradle и постепенно затягивайте проверки в CI.
3. Какой симптом видит пользователь? Холодный старт → Baseline Profiles + R8 Full. Рывки при скролле → Vkompose + гигиена state. Рывки в анимациях → Modifier.Node + профилирование GPU.
4. Кросс-платформенный охват? Только Android → полный стек Vkompose. Compose Multiplatform → многослойный подход с профилировщиками под каждую платформу.
5. Где сегодня контролируется производительность? Нигде → начните с Detekt + Vkompose Gradle в CI прежде, чем править исходники. Уже в CI → затягивайте бюджеты и добавляйте Macrobenchmark.
Грабли, на которые мы видели, как наступают Compose-команды
1. Аннотировать всё подряд как @Stable. Враньё компилятору прячет рекомпозиции вместо того, чтобы их чинить. Сбой приходит позже, и отлаживать его сложнее.
2. Откладывать Strong Skipping «пока не будем готовы». Он готов к продакшену и бесплатен. Включить его позже значит написать аннотации, которые вам не были нужны.
3. Воспринимать Layout Inspector как инструмент для CI. Он только интерактивный. Встройте в пайплайн Macrobenchmark и Vkompose Gradle, а Layout Inspector оставьте для точечной отладки.
4. Рефакторить state, не измерив сперва. Спекулятивные правки формы state часто ломают что-то ещё. Всегда снимайте базовый замер Macrobenchmark до, после и спустя неделю.
5. Игнорировать режим R8 Full. +30% к скорости запуска бесплатно — не опция в 2026 году. Убедитесь, что правила обфускации не ломают зависимости с активным использованием рефлексии, и выкатывайте.
KPI — что измерять и что закладывать в бюджет
KPI по качеству. Время кадра по P95 < 16 мс во время скролла, время до первого кадра < 500 мс при холодном старте, доля ANR < 0,1% сессий, соотношение рекомпозиций к пропускам < 1,5 на «горячих» экранах.
Бизнес-KPI. Доля сессий без сбоев выше 99,5%, изменение retention на 1-й день после каждого релиза по производительности, показатель «плохого поведения» в Play Store Vitals ниже порога (сейчас 0,47% медленных кадров).
KPI по надёжности. Аптайм гейта в CI, разброс Macrobenchmark менее 5% между прогонами, время на локализацию деградации менее часа. Без стабильного бенчмарка вы не сможете отстоять бюджет производительности.
Когда НЕ стоит вкладываться в тяжёлый инструментарий Compose
Соло-разработчик на MVP из пяти экранов, хобби-проект или фича-флаг, который компания вот-вот свернёт, — ни один из них не оправдывает стоимость разворачивания Vkompose, Detekt и Macrobenchmark в CI. Для них хватит включить Strong Skipping вместе с отчётами компилятора и двигаться дальше.
Вложение становится очевидным, когда продукт переваливает за ~50 экранов, команда растёт больше ~5 Android-инженеров или VIP-клиент жалуется на подтормаживания. За этими порогами Vkompose+CI окупается за один спринт.
Хотите список задач, а не теорию?
Пришлите свой репозиторий — мы прогоним Vkompose, Detekt и Macrobenchmark и вернём приоритизированный план исправлений с оценками трудозатрат в течение десяти дней.
Частые вопросы
Vkompose поддерживает Фора Софт?
Нет. Vkompose — open source от Android-команды VK.com. Фора Софт использует его на проектах с активным Compose, потому что это самый жёсткий open-source-набор для блокировки неоптимизированного Compose-кода на этапе компиляции.
Включать Strong Skipping Mode сейчас или подождать?
Сейчас. Он готов к продакшену в Compose Compiler 2.0+, закрывает около 30% проблем рекомпозиции без изменений в коде и является самой дешёвой мерой в наборе. Включайте его прежде любой работы с аннотациями.
Чем Vkompose отличается от Rebugger?
Rebugger — библиотека логирования в рантайме, лёгкая и удобная для трассировки по ходу дела. Vkompose — полный набор (плагин для IDE, плагин для Gradle, правила Detekt), который может ронять сборки при обнаружении неоптимизированного кода. Они дополняют друг друга; на больших кодовых базах мы используем оба.
Работает ли Vkompose с Compose Multiplatform?
Нет. Vkompose работает только под Android, потому что интегрируется с плагином Android Gradle. Кросс-платформенным Compose-командам нужно добавить Macrobenchmark, метрики компилятора Compose Multiplatform и профилировщики под каждую платформу.
Какое самое дешёвое одиночное изменение для времени запуска Compose?
Переключение на proguard-android-optimize.txt с режимом R8 Full и поставка Baseline Profile, сгенерированного из вашего главного пользовательского сценария. Вместе они стабильно убирают 25–35% от холодного старта.
Сколько стоит аудит производительности Compose в Фора Софт?
450 тыс.–900 тыс. ₽ за полный аудит (отчёты компилятора, прогон Vkompose, трассировки Layout Inspector, базовый замер Macrobenchmark, приоритизированный список задач с оценками трудозатрат). Большинство клиентов затем заказывают исправления уровня Tier-1, которые обходятся в 750 тыс.–1,8 млн ₽.
Готов ли Compose для крупных продакшен-команд?
Да. Twitter, Reddit и Square используют Compose в больших масштабах. Инструментарий (Vkompose, Detekt, Layout Inspector, Macrobenchmark, Baseline Profiles) достаточно зрелый для команд из 100+ инженеров. Планка сегодня — дисциплина по производительности, а не готовность фреймворка.
Фора Софт работает только с Android или с полным мобильным стеком?
И так, и так. Мы выпускаем проекты на Android, iOS, KMP и Compose Multiplatform. Представление о наших работах дают наши итоги мобильной разработки за 2024 год.
Что почитать дальше
Готовы сделать Compose быстрым и удержать эту скорость?
Jetpack Compose достаточно быстр для продакшена — когда команды держат форму state чистой, лямбды стабильными, а область рекомпозиции узкой. Инструментарий, который обеспечивает эту дисциплину, существует уже сегодня: Strong Skipping, Vkompose, Detekt, Layout Inspector, Modifier.Node, Baseline Profiles, R8 Full. Соберите их вместе, встройте в CI — и ваш Android-продукт перестанет менять производительность на декларативное удобство.
Если хотите применить эту дисциплину к своей кодовой базе — или получить список того, что чинить в первую очередь, — позвоните нам или напишите. Мы просканируем, оценим и предложим план исправлений с оценками трудозатрат за десять дней, а не за десять недель.
Поговорите с нашими лидами Android-разработки
Свяжитесь с нами. Мы разберём Vkompose, Strong Skipping, R8 Full и остальное руководство применительно к вашей кодовой базе.
