Is there any cost of Higher Order Functions? I can solve some problems with it easily but I am not sure can it effect performance. Are there any limitations about it?
Kotlin functions are first-class, which means they can be stored in variables and data structures, and can be passed as arguments to and returned from other higher-order functions.
In Kotlin, a function which can accept a function as parameter or can return a function is called Higher-Order function. Instead of Integer, String or Array as a parameter to function, we will pass anonymous function or lambdas. Frequently, lambdas are passed as parameter in Kotlin functions for the convenience.
Unit in Kotlin corresponds to the void in Java. Like void, Unit is the return type of any function that does not return any meaningful value, and it is optional to mention the Unit as the return type. But unlike void, Unit is a real class (Singleton) with only one instance.
Lambdas passed to higher-order functions are compiled to generic Function
objects. This approach certainly adds some costs, also due to boxing overhead when primitive types are involved.
So yes, it can effect performance. You should use inline
higher order functions whenever it makes sense because the aforementioned caveats won’t be problematic anymore.
Taken 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.
There are certain restrictions for inline
though. Read in the docs.
Definition of higher-order function and caller code:
fun hoFun(func: (Int) -> Boolean) {
func(1337)
}
//invoke with lambda
val mod = 2
hoFun { it % mod == 0 }
Bytecode Java Representation:
public static final void hoFun(@NotNull Function1 func) {
Intrinsics.checkParameterIsNotNull(func, "func");
func.invoke(1337);
}
final int mod = 2;
hoFun((Function1)(new Function1() {
public Object invoke(Object var1) {
return this.invoke(((Number)var1).intValue());
}
public final boolean invoke(int it) {
return it % mod == 0;
}
}));
As mentioned, the lambda is compiled to a Function
object. Each invocation leads to the instantiation of a new Function
object because the mod
needs to be captured. Non-capturing lambdas use singleton Function
instances instead.
With inline
modifier applied to the higher-order function the compiled call looks much better:
int mod = 2;
int it = 1337;
if (it % mod == 0) {
;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With