Kotlin-inline: Everything you need to know(Android)

Kotlin-inline: Everything you need to know(Android)

From Doc,

“Using higher-order functions imposes certain runtime penalties: each function is an object, and it captures a closure. A closure is a scope of variables that can be 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.”

Let’s explore together…

fun main() {
    me({
        println(it)
    }, {
        println(it)
    })
}

fun me(myName: (String) -> Unit, myAge: (Int) -> Unit) {
    myName("Christiano")
    myAge(36)
}

Without inline keyword, if you see Kotlin byte code, you will notice two new instances of special function types is created. Two new instances will allocate memory.

However, here extra method call also happens. See the Kotlin decompile code carefully.

myName.invoke("Christiano");
myAge.invoke(36);
// (Function1)null.INSTANCE, (Function1)null.INSTANCE 
// instance of two higher order function

When these above code execute it also create two new function. Hence memory overhead.

Kotlin byte code decompile (Java code)

public final class TestInlineKt {
   public static final void main() {
      me((Function1)null.INSTANCE, (Function1)null.INSTANCE);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

   public static final void me(@NotNull Function1 myName, @NotNull Function1 myAge) {
      Intrinsics.checkNotNullParameter(myName, "myName");
      Intrinsics.checkNotNullParameter(myAge, "myAge");
      myName.invoke("Christiano");
      myAge.invoke(36);
   }
}

So, New special instance of special type is created and allocate memory. Extra method call always happens.

With inline function, there is no extra object allocation and no extra method calls. Lets see Decompile code.

public static final void main() {
      int $i$f$me = false;
      String it = "Christiano";
      int var2 = false;
      System.out.println(it);
      int it = 36;
      var2 = false;
      System.out.println(it);
}

With the help of inline function there is no extra method call but it substitute directly into the main code.

Because of the inline keyword, compiler copies the content of the inline function to the call site avoiding creating a new function object.

Decompile code using inline keyword

public final class TestInlineKt {
   public static final void main() {
      int $i$f$me = false;
      String it = "Christiano";
      int var2 = false;
      System.out.println(it);
      int it = 36;
      var2 = false;
      System.out.println(it);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

   public static final void me(@NotNull Function1 myName, @NotNull Function1 myAge) {
      int $i$f$me = 0;
      Intrinsics.checkNotNullParameter(myName, "myName");
      Intrinsics.checkNotNullParameter(myAge, "myAge");
      myName.invoke("Christiano");
      myAge.invoke(36);
   }
}

To see that there is not object allocation. Go to tools->Kotlin->Show Kotlin ByteCode. Now search for new keyword. Hence you will find no new keyword in the bytecode.

1*d8t5TbaabIdTFsT3MPVpoQ.png

Note:

  • Don’t use inline keyword for large function.
  • Don’t use inline keyword where there is no higher order function as parameter. Because you won’t get significant performance benefits.

Thanks for reading. Show me love by following and applause.