How are Lambdas compiled to bytecode

I am writing a paper about a comparison between the lambda performance of Java and Kotlin (targeting JVM). Kotlin is signifacantly faster, but I can t find hints for that in the bytecode. So I need to know how exactly lamdas and higher-order functions are compiled to bytecode, and what the main difference are to the lambda compilation in Java.

Hi @hendrik.reiter,

It is really strange, you should prove it.
Please strongly consider to use a well-written JMH benchmark.

You have to decompile your test and spot differences.
Moreover, to provide a valuable paper, you should compare differences in C2 compiled code in assembly language.

Thanks for your fast response,

Indeed, it was strange for me as well. But over all my Benchmarks (written with JMH, just testing the most common higher-order functions) Kotlin has an advantage in speed.

I did that, but there is only the reference to the Kotlin filter Method, where i can t get more information about. Java is using the LambdaMetaFactory to create the anonymous inner class but i can t find out how Kotlin is doing that. Do you have more information about that?
Analyzing it on Assembly-Level would go a little bit beyond the scope of my paper.

Regarding the collection performance - please take a look on this Russian article. Author described a little difference.

And there is another article (it is Russian too, sorry), which describes byte code (and possible performance benefits).

1 Like

Can you share the filter's signature, please?
Are you seen the Kotlin’s reference documentation?

public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
    for (element in this) if (predicate(element)) destination.add(element)
    return destination
}

This is the implementation in kotlin

    LOCALVARIABLE it I L10 L13 9
    LOCALVARIABLE $i$a$-filter-KotlinFunctionsKt$main$1 I L11 L13 10
    LOCALVARIABLE element$iv$iv Ljava/lang/Object; L9 L14 8
    LOCALVARIABLE $this$filterTo$iv$iv Ljava/lang/Iterable; L5 L15 4
    LOCALVARIABLE destination$iv$iv Ljava/util/Collection; L5 L15 5
    LOCALVARIABLE $i$f$filterTo I L6 L15 6
    LOCALVARIABLE $this$filter$iv Ljava/lang/Iterable; L3 L16 2
    LOCALVARIABLE $i$f$filter I L4 L16 3

And these are the references in bytecode

So the filterTo method was inlined, in this case no extra class was generated.

Other cases are:

  • not inlined lambda (no capturing scope)
  • not inlined clojure (with capturing scope)

Thanks, the inlining has a big impact on the performance. That could be an argument why in my test cases Kotlin is faster.