Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are Kotlin inline functions less expensive than Java anonymous classes?

Tags:

java

kotlin

Heads up: I'm writing some of this from memory so I may have some of the concepts incorrect.


Java has the ability to write an anonymous function. This is useful when you have a listener interface for some kind of event. As an example:

button.setOnClickListener(new View.OnClickListener(View v) {
    @Override
    public void onClick(View v) {
        // handle the action here
    }
});

The anonymous listener will be compiled as a class that is called something like OnClickListener$1.class. This is an underlying design decision of the Java language. Everything is an object, even anonymous functions.

This becomes an issue when you want to write a more functionally driven code base. The large amount of anonymous classes creates a large class count, which can be a problem on constrained platforms such as Android.

In Kotlin functions are much more first class from a source code point of view. My question is, does Kotlin compile these functions down to byte code more efficiently than Java does with anonymous classes or will I run into the same issues as the large class count in Java?

Thanks,

like image 255
Brad Avatar asked May 19 '17 01:05

Brad


2 Answers

The short answer is yes, the Kotlin inline functions are quite cheap.

When an inline function call is compiled, the lambdas passed to the call get inlined into the function body, which is in turn inlined at the call site. This allows the compiler not to generate any additional classes or methods for the lambda bodies.

Compilation of an inline function

One of the slides about Kotlin constructs compilation by @yole. Unfortunately, I found the record only in Russian. The other slides are also of some interest, you can find more about non-inlined lambdas there.

In general, the Kotlin code that uses inline functions with lambdas works faster than the identical Java code with lambdas or Streams. All the code binding is done at compile-time, and there is no runtime overhead of virtual method calls, nor increased methods count, which matters for Android.

The downside of excessive inlining is the code size growth: the common part of the bytecode of an inline function body gets actually duplicated at the call sites. Also, inlining complicates debugging, because the line numbers and the call stack of the code will differ from what was in the source file. Though the IDE support can help here.

I would recommend you to experiment with inline functions yourself: you can easily inspect the resulting bytecode; and, of course, do some benchmarking of your particular use cases where performance matters.

like image 81
hotkey Avatar answered Oct 10 '22 22:10

hotkey


Kotlin has an inline keyword. If you use this keyword, not only does it inline the function but you can treat the lambda body as if it was just a nested scope level, so that you can return from it!

Example (straight from the docs)

fun foo() {
    inlineFunction {
        return // OK: the lambda is inlined
    }
}

Check out the docs for more:

https://kotlinlang.org/docs/reference/inline-functions.html

Edit:

To clarify your exact question about performance, this is the first paragraph from the docs:

Using higher-order functions imposes certain runtime penalties: each function is an object, and it captures a closure, i.e. those variables that are accessed in the body of the function. Memory allocations (both for function objects and classes) and virtual calls introduce runtime overhead.

But it appears that in many cases this kind of overhead can be eliminated by inlining the lambda expressions.

So as far as I can tell yes, it will inline the function and remove any overhead that would otherwise be imposed.

However, this seems to only apply to functions you declare as inline.

like image 37
hasen Avatar answered Oct 10 '22 23:10

hasen