Inline Functions
In this page:
Declaring an Inline Function
Adding inline before fun tells the compiler to insert the function's compiled code directly at each call site instead of a normal function call, which avoids extra lambda object allocation for its function-type parameters.
Example: Declaring an Inline Function
inline fun measureAndRun(action: () -> Unit) {
val start = System.currentTimeMillis()
action()
val time = System.currentTimeMillis() - start
println("Took ${time}ms")
}
fun main() {
measureAndRun {
println("Doing some work")
}
}
Login to try C/C++/Java/PHP code in the editor
Why Inlining Avoids Overhead
Normally, passing a lambda creates an object implementing a function interface behind the scenes; inlining removes that indirection entirely by copying the lambda's code straight into the call site.
Example: Why Inlining Avoids Overhead
inline fun repeatAction(times: Int, action: (Int) -> Unit) {
for (i in 0 until times) {
action(i)
}
}
fun main() {
repeatAction(3) { index ->
println("Iteration $index")
}
}
Login to try C/C++/Java/PHP code in the editor
Non-Local Returns Require inline
A plain return inside a lambda passed to a function is only allowed when that function is inline, because the lambda's code becomes part of the calling function itself after inlining.
Example: Non-Local Returns Require inline
inline fun findFirst(numbers: List<Int>, predicate: (Int) -> Boolean): Int? {
for (n in numbers) {
if (predicate(n)) return n
}
return null
}
fun main() {
val result = findFirst(listOf(1, 2, 3, 4)) { it > 2 }
println("First match: $result")
}
Login to try C/C++/Java/PHP code in the editor
noinline and crossinline
noinline marks one specific lambda parameter as excluded from inlining (useful if it needs to be stored or passed elsewhere), while crossinline allows inlining a lambda but forbids it from performing a non-local return.
Example: noinline and crossinline
inline fun runTasks(crossinline first: () -> Unit, noinline second: () -> Unit) {
val wrapped = Runnable { first() }
wrapped.run()
second()
}
fun main() {
runTasks({ println("First task") }, { println("Second task") })
}
Login to try C/C++/Java/PHP code in the editor
- Marking a huge function
inlineexpecting a performance win, when inlining large functions can actually bloat compiled code without meaningful benefit. - Forgetting that a non-local
returninside a lambda only works because the enclosing function accepting that lambda isinline. - Using
noinlineorcrossinlineincorrectly on lambda parameters that don't need those special behaviors.
inline funtells the compiler to substitute the function's body (and its lambda parameters) directly at each call site.- Inlining avoids the runtime overhead of creating a separate object for each lambda passed to the function.
- Non-local returns from a lambda are only possible because the function receiving it is inlined.
noinlinemarks a specific lambda parameter as exempt from inlining, andcrossinlineforbids non-local returns from a specific inlined lambda.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: