I know that an inline function will maybe improve performance & cause the generated code to grow, but I'm not sure when it is correctly to use it.
lock(l) { foo() }
Instead of creating a function object for the parameter and generating a call, the compiler could emit the following code. (Source)
l.lock()
try {
foo()
}
finally {
l.unlock()
}
but I found that there is no function object created by kotlin for a non-inline function. why?
/**non-inline function**/
fun lock(lock: Lock, block: () -> Unit) {
lock.lock();
try {
block();
} finally {
lock.unlock();
}
}
The most important case when we use inline modifier is when we define util-like functions with parameter functions. Collection or string processing (like
filter
,ma
p orjoinToString
) or just standalone functions are perfect example.This is why inline modifier is mostly an important optimization for library developers. They should know how does it work and what are its improvements and costs. We will use inline modifier in our projects when we define our own util functions with function type parameters.
When we don’t have function type parameter, reified type parameter, and we don’t need non-local return, then we most likely shouldn’t use inline modifier. This is why we will have a warning on Android Studio or IDEA IntelliJ.
Also there is the code size problem. Inlining a large function could dramatically increase the size of the bytecode because it's copied to every calls site. In such cases, you can refactor the function and extract code to regular functions.
Let's say you create a higher order function that takes a lambda of type
() -> Unit
(no parameters, no return value), and executes it like so:In Java parlance, this will translate to something like this (simplified!):
And when you call it from Kotlin...
Under the hood, an instance of
Function
will be created here, that wraps the code inside the lambda (again, this is simplified):So basically, calling this function and passing a lambda to it will always create an instance of a
Function
object.On the other hand, if you use the
inline
keyword:When you call it like this:
No
Function
instance will be created, instead, the code around the invocation ofblock
inside the inlined function will be copied to the call site, so you'll get something like this in the bytecode:In this case, no new instances are created.