3 ms·
yes, String.valueOf() is dog slow. We recently moved all logging stuff to use a constant lambda as first parameter, log.info(s -> "Foo: " + s, "bar") so if the
by _old_dude_ 9y ago
yes, String.valueOf() is dog slow.
We recently moved all logging stuff to use a constant lambda as first parameter, log.info(s -> "Foo: " + s, "bar") so if the logger is not enabled, the constants are discarded by the VM and otherwise the string concatenation is faster than any string interpolations.
- sk5t 9y agoHave you measured this? I would expect the allocation of Callable<String> with closures to be slightly worse than common types of string concatenation. Not to mention the awkwardness of only logging effectively final vars--this would be a red flag on organizational coding practices--just use slf4j or better yet Scala + LazyLogging.
- _old_dude_ 9y agoIf you use a closure that capture some local variables and not a constant lambda, then you're right, the allocation will kill you. But, we are only using lambdas that do not capture anything so the lambda is allocated once by the VM. And we are using the new shiny System.Logger [1] so the VM logs and the application logs are interleaved. We still have some wrappers to redirect log4j logs on the system logger because few third party libs are compatible with the system logger. [1] https://docs.oracle.com/javase/9/docs/api/java/lang/System.Logger.html https://docs.oracle.com/javase/9/docs/api/java/lang/System.L...
- sk5t 9y agoAh, makes sense. On the other hand, this would seem to take a StringBuilder-based approach off the table (cf. logback). I wonder how this stacks up to simply passing varargs to the logger. There's also the question of applying any strategy other than toString to the non-string args.
- specialist 9y agoHuh. I'll have to try that. Thanks. My solution was to flip the problem, making a separate logger instance for each log level. So something like Logger warn = Logger.factory(Level.WARN); warn.log( "message" ); If warn is disabled, factory returns a NullObject (do nothing) logger. (My actual implementation had one level of indirection, so logs levels could be updated at runtime.) Then I got nutty optimizing printf, doing JIT class generation per template... But that's another story. TL;DR: Logging in Java drives me nuts, so I made my own.
- _old_dude_ 9y agoDid you take a look to java.lang.invoke.StringConcatFactory, it does more or less what you want using method handles instead of bytecode generation ?
- specialist 9y agoThanks for the tip. Will check it out. I'll be happy if it moots my hackery.
- deleted 9y ago[deleted]
- cbsmith 9y agoWait, your string literals are still going to get intern'd, regardless of whether they are in a Lambda or not.