Kotlin Tip #14: Use Inline Functions to Avoid Performance Overhead — 100 Kotlin Tips in 100 Days

Raphael De Lio
Kotlin with Raphael De Lio
2 min readFeb 23, 2024

Twitter | LinkedIn | YouTube | Instagram
Tip #13: Manage Lambda Expressions with Label References

In tip #9 we talked about Higher-Order functions, functions that take other functions as parameters or/and return a function.

Examples of higher-order functions are all over the Collections file in Kotlin's Standard Library. One example is the forEach inline extension function:

public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}

This function receives a lambda (an anonymous function) as a parameter and invokes this function for each element in the collection.

The best way to understand what the inline keyword is doing there is by decompiling our Kotlin bytecode and checking what it translates to.

fun main() {
listOf(1, 2, 3, 4, 5).forEach {
println(it)
}
}

If we decompile the code above, we will that it's translated to:

fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
for (number in numbers) {
println(number) //pay attention here
}
}

Pay close attention here and you will see that translated code is calling the println() function on each iteration. This is important because if we remove the inline keyword and decompile our code once again, we will that it translates to:

fun main() {
listOf(1, 2, 3, 4, 5).forEach {
println(it)
}
}

fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) {
action(element) //pay attention here
}
}

Without the inline keyword, instead of embedding the println call directly within the loop, the generated bytecode invokes the action lambda for each element. This is dangerous because lambdas in Kotlin are objects. This means that for each lambda invocation, a new object will be created.

In scenarios where we're dealing with large collections, a function may be called numerous times, leading to significant memory consumption and performance overhead.

Moreover, for applications running on devices with limited memory, this can quickly become a bottleneck, potentially leading to OutOfMemoryError exceptions.

Therefore, to avoid memory overhead when writing HOFs, don't forget to mark them as inline.

I hope you have enjoyed the fourteenth tip of our series! Don’t forget to subscribe and stay tuned for more Kotlin tips!

Stay curious!

Tip #15: Use Objects to Create Singletons

Contribute

Writing takes time and effort. I love writing and sharing knowledge, but I also have bills to pay. If you like my work, please, consider donating through Buy Me a Coffee: https://www.buymeacoffee.com/RaphaelDeLio

Or by sending me BitCoin: 1HjG7pmghg3Z8RATH4aiUWr156BGafJ6Zw

Follow Me on Social Media

Stay connected and dive deeper into the world of Kotlin with me! Follow my journey across all major social platforms for exclusive content, tips, and discussions.

Twitter | LinkedIn | YouTube | Instagram

--

--