Reputation: 157
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)
}
Upvotes: 1
Views: 326
Reputation: 93902
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:
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
.
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.
Upvotes: 1