Inline Functions in Kotlin
Introduction
Hi, everyone👋
Anyone here who wants to improve Kotlin code performance? 🤔 I will talk about Inline functions, which is one of the important functions. I will try to explain what they are, how they are used or how they are kept in the background, etc. At the same time 👇
- From the use cases of the inline functions
- What is the
noinline
keyword? - What is the
crossinline
keyword? - What is the
reified
keyword?
Let’s get started then ✨
🔶 Inline Functions
- Inline functions are copied to where they were called at compile time.
- No real function calls are made. All code between the function body is pasted wherever inline functions were called. In this way, no additional function object is created. Memory load is reduced with inline functions.
Let’s look at the following code examples for better understanding. 👇
Let’s write a normal function without using the inline keyword. Then let’s make the same example with the inline function and compare 💥
Normal Function:
Now let’s examine it with Show Kotlin Byte Code
Tools -> Kotlin -> Show Kotlin Bytecode -> Decompile ✨
As seen in the show Kotlin bytecode, secondFunc() is called normally. What happens if I put the inline keyword at the beginning of secondFunc() ? 🤔
With Inline keyword:
Now let’s examine it with Show Kotlin Byte Code
As you can see the body of secondFunc() is copied to where it was called. A normal function call as above was not made. What good does a call like this do for us? 🤔
As I mentioned above, the function object is not created because the body of the inline function is copied directly to the place where it is called.
NOTE: In order to reduce the memory load of higher order functions or lambda expressions, the
“inline”
keyword is used to ask the compiler not to allocate memory.
As an example, let’s look at the code below.
In case the inline keyword is not used with higher order functions 👇
Now let’s examine it with Show Kotlin Byte Code
As you can see in Kotlin bytecode, when we call HigherOrderFunc() it generates Function object
.
NOTE: So, what if I want to call this HigherOrderFunc() more than once? 🤔
Each time HigherOrderFunc() is called, a new Function object is created, and memory starts to swell. 😲
That’s why we use the inline keyword
. In this way, we avoid creating a new Function object
by copying the body of our function to the place where it was called. ❗️❗️❗️
- Inline functions allow
non-local return
. For example:
🔶 Noinline and Crossinline Keyword
- When we do
not want to inline
the parameter in a function that we have created as inline, we put the“noinline”
keyword in front of the parameter. - If we want the operation to be inline but in a
different scope
, we use the“crossinline”
keyword. Crossinline does not allow non local return. In crossline, object creation does not occur in the background, as in inline.
For example:
fun main(){
test()
}
fun test(){
println("Hello!")
higherOrderFuncExample({
println("crossinline")
},{
println("noinline")
})
}
interface testI{
fun test() : Unit
}
inline fun higherOrderFuncExample(crossinline printInfo: () -> Unit, noinline callback: () -> Unit) {
val test = object : testI{
override fun test(): Unit {
return printInfo.invoke()
}
}
callback()
}
🔶 Reified Keyword
- Generic types do not know what type they are at compile time. If the reified keyword is used with inline functions, then it is known at compile time what type T can be.
Now let’s examine it with Show Kotlin Byte Code
Conclusion
Inline functions are a nice function that can be used to improve your code performance. Especially using it together with higher order functions and lambda expressions increases the performance and reduces the memory load.
However, since the body part of the inline functions is directly pasted into the function they are called, the code size may increase and accordingly the bytecode size may increase. Therefore, the use of inline functions with large or complex functions should be avoided.