Когда использовать inline-функции в Kotlin и как они влияют на производительность?
Когда использовать inline-функции: полный разбор
Отличный вопрос! Давайте разберёмся по порядку. inline — это не магическая кнопка "сделай быстро", а инструмент с чёткой областью применения.
Как работает inline?
Обычная функция высшего порядка:
fun measureTime(action: () -> Unit) { ... }
На уровне JVM создаётся объект-функция (лямбда). При каждом вызове — новый объект. inline говорит компилятору: "вставь тело функции прямо в место вызова, не создавая объект".
Без inline:
// Создаётся анонимный класс Function0
val lambda = object : Function0 {
override fun invoke() {
Thread.sleep(100)
println("Hello")
}
}
measureTime(lambda)
С inline:
// Копируется тело функции
val start = System.currentTimeMillis()
Thread.sleep(100)
println("Hello")
val end = System.currentTimeMillis()
println("Time: ${end - start} ms")
Когда использовать inline — чёткие критерии
- Функции с лямбда-параметрами — основное применение. Если ваша функция принимает другую функцию как параметр (например,
measureTime), и эта лямбда вызывается внутри — ставьтеinline. - Маленькие функции, вызываемые в циклах — если функция вызывается тысячи раз, накладные расходы на создание объектов становятся заметными.
- Reified (вещественные) типы — да, вы правы. Только
inlineпозволяет использоватьreified, потому что на уровне JVM generic-типы стираются, а inline-функция "встраивает" реальный тип в место вызова.
Пример с reified:
inline fun <reified T> isType(value: Any): Boolean {
return value is T // Работает только с inline + reified
}
Когда НЕ стоит использовать inline
- Большие функции — встраивание увеличивает размер байт-кода (code bloat). Если функция содержит 100+ строк, её копирование в каждое место вызова — плохая идея.
- Функции без лямбда-параметров — обычные функции не выигрывают от inline. Компилятор сам может оптимизировать их без вашего вмешательства.
- Прямые рекурсивные вызовы — inline не работает с рекурсией.
Практический пример: когда inline реально помогает
Представьте, что вы пишете DSL или библиотеку с часто вызываемыми функциями:
inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
val sb = StringBuilder()
sb.builderAction()
return sb.toString()
}
// Использование
val result = buildString {
append("Hello, ")
append("World!")
}
println(result) // "Hello, World!"
Без inline каждый вызов buildString создавал бы новый объект лямбды. С inline — никаких лишних объектов.
Итоговые рекомендации
- Используйте
inlineдля функций высшего порядка с лямбдами, особенно если они вызываются часто. - Используйте
inline+reified, когда нужно сохранить тип в runtime. - Не используйте
inlineдля больших функций или функций без лямбда-параметров. - Помните: компилятор Kotlin/JVM сам делает много оптимизаций.
inline— это когда вы хотите контролировать процесс вручную.
Надеюсь, теперь стало понятнее! Если сомневаетесь — начните с inline только для функций с лямбдами, и вы не ошибётесь.
Дополнение: производительность и профилирование
Коллега дал отличный ответ, добавлю важный нюанс.
Не стоит думать, что inline всегда делает код быстрее. Современная JVM (HotSpot) имеет JIT-компилятор, который сам умеет "встраивать" (inline) маленькие функции на лету, независимо от того, поставили вы модификатор или нет. Разница часто незаметна в обычных приложениях.
Где inline реально даёт прирост:
- Android-разработка — там нет JIT (только AOT), поэтому лишние объекты — это реальные затраты памяти и GC.
- Библиотеки/фреймворки — если вашу функцию будут вызывать миллионы раз (как
let,apply,withв стандартной библиотеке). - Hot path в критическом коде — например, в игровом движке или обработке данных в реальном времени.
Совет: не оптимизируйте заранее. Пишите сначала читаемый код, потом профилируйте. Если профилировщик (например, Android Studio Profiler) показывает, что создание лямбд — узкое место — вот тогда ставьте inline.
И ещё: inline может сломать return в лямбдах (non-local return). Это отдельная тема, но помните: с inline лямбда может делать return из внешней функции, что иногда неожиданно.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги