Inline function : Kotlin

Suneet Agrawal
Apr 15 · 3 min read

What is inlining?

Inlining is basically requesting the compiler to copy the (inlined) code at the calling place.

Why it is required?

When a program is executed and a function is called, CPU stores the memory address of the instruction following the function call, copies the arguments of the function into a stack and finally transfers control to the specified function. The CPU then executes the function code, stores the function return value in a predefined memory location/register and returns control to the calling function.

In Kotlin, the higher order functions or lambda expressions, all stored as an object which takes some memory and might increase the memory overhead. Sometimes, the function does a very basic functionality that passing the control is not even worth but as it (the function) is being used at multiple places, we need to create a separate function. To reduce the memory overhead of such functions we can use the inline keyword which ultimately requests the CPU to not allocate any memory for the function and simply copy the body of that function at the calling place.

Let’s take an example.

suppose we have a function which simply checks if the first argument is a multiple of the second argument and returns a boolean.

fun isMultipleOf (number: Int, multipleOf : Int): Boolean{
return number % multipleOf == 0
}

Now to use this function as a higher order function,

fun <T> ArrayList<T>.filterOnCondition(condition: (T) -> Boolean): ArrayList<T>{
val result = arrayListOf<T>()
for (item in this){
if (condition(item)){
result.add(item)
}
}
return result
}
var list = arrayListOf<Int>()
for (number in 1..10){
list.add(number)
}
val resultList = list.filterOnCondition { isMultipleOf(it, 5) }
print(resultList)

In the above example, the functionality of the isMultipleOf is so small that it can be copied but as it can be used at multiple places, we created it as a separate function. As this function is passed as an argument to filterOnCondition function, CPU will assign it to some object which will take some memory. Also, for every item in the list, the CPU will jump to the memory address of isMultipleOf function and will pass back to result.

To prevent this, we can make the isMultipleOf function as inline which will as the compiler to copy it to the calling place which will prevent the memory allocation of the function and jumping of the CPU at runtime.

inline fun isMultipleOf (number: Int, multipleOf : Int): Boolean {
return number % multipleOf == 0
}

The functionality will remain the same.

Things to keep in mind

  • We will lose access to any private variable or function of the class inside the inline function. So it’s better to make functions inline which are very generic and don’t use a class level variable or function to achieve their functionality.
private var localVariable : Int = 8inline fun isMultipleOf (number: Int, multipleOf : Int): Boolean {
print(localVariable) //compilation error
return number % multipleOf == 0
}

The above code will show compilation error

Public-API inline function cannot access non-public-API 'private var localVariable

Which is clear in itself.

  • Do not inline for bigger functions as it degrades the performance.

That’s all for now. You can read my other interesting posts here or you can enjoy my games or apps listed here. Feel free to use my open source Android components in your app listed here. Or drop an email, if you didn’t find what you are looking for and need some help.

Suneet Agrawal

Written by

https://agrawalsuneet.github.io/

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade