-
-
Notifications
You must be signed in to change notification settings - Fork 124
Closed
Description
It seems that the whole fuzz around logging is to not create "expensive" String
object, if logging level is not enabled. That totally makes sense.
And that's why we library offers a nice function:
fun unknownElementType(elementType: Int) {
// Lazy evaluation of the log message
log.warn { "Unknown element: $elementType" }
}
So, what gets generated for this line?
this.log.warn((Function0)(new Function0() {
// $FF: synthetic method
// $FF: bridge method
public Object invoke() {
return this.invoke();
}
@NotNull
public final String invoke() {
return "Unknown element: " + elementType;
}
}));
Hm... instead of a String
, we create:
- An anonymous inner class
- Instance of this class, which gets the closure reference to all required outer variables like
elementType
That doesn't look very cheap to me.
On the other hand, in Kotlin StdLib pretty much all map
or forEach
functions are inline
. So, we might write it like this:
inline fun KLogger.warnInline(message: () -> String) {
if (underlyingLogger.isWarnEnabled)
underlyingLogger.warn(message())
}
And this gets compiled to the simplest possible, desired lazy evaluation of String:
void unknownElementType(int elementType) {
KLogger $receiver$iv = this.log;
Logger logger$iv = $receiver$iv.getUnderlyingLogger();
if (logger$iv.isWarnEnabled()) {
// Lazy evaluation of the log message
String var7 = "Unknown element: " + elementType;
logger$iv.warn(var7);
}
}
Just like we wanted in the first place.
Displee, qoomon, vitaliyistomov, yuriykulikov, jasonCodesAway and 10 more
Metadata
Metadata
Assignees
Labels
No labels