Home > Enterprise >  Why do we use inline keyword on a variable in kotlin?
Why do we use inline keyword on a variable in kotlin?

Time:01-29

What I can understand from google documentation is that we can use inline keyword to enhance the performance and reduce the memory allocation on runtime in case of high order function but why in this case we are inlining a variable

@PublishedApi
internal inline val <T : Any> T.loggingTag: String
    get() {
        val tag = this::class.java.name.substringAfterLast(".")
        if (tag.contains("$")) {
            return tag.substringBefore("$")
        }

        return tag
    }

in case you are curious the logging tag variable is used in an inline function

inline fun <reified T : Any> T.errorLog(error: Throwable? = null, message: String? = null) {
    errorLog(loggingTag, error, message)
}

also the errorLog function inlined even it doesn't take an other function as a parameters does anyone able to explain for me this ?

inline fun errorLog(tag: String, error: Throwable? = null, message: String? = null) {
    Timber.tag(tag).e(error, message)
}

CodePudding user response:

The inline keyword is used to make functions inline, meaning that when a function is called, its body is copied and pasted into the caller's code instead of making a function call. This allows for reduced execution time, as there is no need to jump to another function and back. Inline functions can also be used to reduce code size and improve readability.

CodePudding user response:

That val isn't a variable. It's a property. If you see val or var outside of a function, it's a property, not a variable.

Properties have getter functions. In your example, the getter function is what is being marked as inline.

There are two main reasons to use inline functions:

  1. In a higher order function, it avoids allocating a function object to represent the function parameter (lambda or function reference) being passed to it. It also allows lambdas that are passed to use keywords that are normally restricted to local use, such as return, break, and continue.

  2. It is necessary for reified generics. If a function needs to be able to inspect one of its generic types, the type needs to be marked as reified, which in turn requires the function to be marked inline.

Generally, you want to avoid using inline if a function doesn't fit one of the above cases, because actual function calls themselves are rather trivial, and if you inline a function that is used frequently (the only kind of function you would want to be optimized), then its code is going to be repeated everywhere it's used in your compiled app, increasing the size of the app.

An exception might be if the inline function contains only one function call, so it's not really increasing code size.

I do not see any reason the inline keyword is needed for the extension property in your first block of code. It is not a higher-order function, and it is a multi-line function. I also don't see why it is defined as a generic function, since the type T is not used for anything inside the function. I think I would define it as:

internal val Any.loggingTag: String

Also, in your second block of code, I don't see any reason why there is a generic type, since it is not used in that function. It could be defined as:

fun Any.errorLog(error: Throwable? = null, message: String? = null) {

The third block of code doesn't benefit much from inlining either. It's not a higher-order function. If function call overhead is that much of an issue for performance, it would make more sense to fork Timber and rewrite how it creates tags, because using custom temporary tags like that in Timber involves a few method calls under the hood.

  • Related