Reduce logging overhead - #439
Conversation
schlosna
commented
Aug 15, 2016
- Avoid overhead when logging is disabled.
- Reuse a single StringBuilder when constructing method tag.
|
no issue with guarding on debug, fine, but I'd benchmark before doing the
change to stringbuilder instead of concat. sometimes javac does this stuff
automatically the change to expose the stringbuilder makes the format
string code harder to understand.
http://stackoverflow.com/questions/1532461/stringbuilder-vs-string-concatenation-in-tostring-in-java
|
|
I have a separate local branch I'll push and create a PR later tonight or tomorrow to hook up the benchmarks module and add a small JMH microbenchmark for the StringBuilder, but the main reason I added it was that I saw a bunch of string copies in some profiles since we almost always append an additional format string after generating the method tag format, and sometimes the new line placeholder. There is still another string copy for the String.format, though as already commented in the code we're not doing printf to slf4j message conversion (yet). |
|
Since I asked for the benchmark, I'll share in the pain :) Here's a succinct way to compare (I think). Feel free to use or toss. @Benchmark
public String logBasic_concat() {
return logBasic(concatLogger);
}
@Benchmark
public String logBasic_builder() {
return logBasic(builderLogger);
}
static String logBasic(Logger logger) {
return logger.toLog("Github#contributors", "---> %s %s HTTP/1.1", "GET", "https://api.github.com/repos/openfeign/feign");
}
interface Logger {
String toLog(String configKey, String format, Object... args);
}
static final Logger concatLogger = (configKey, format, args) -> {
String methodTag = new StringBuilder().append('[').append(configKey.substring(0, configKey.indexOf('('))).append("] ").toString();
return String.format(methodTag + format, args);
}
static final Logger builderLogger = (configKey, format, args) -> {
StringBuilder methodTag = new StringBuilder().append('[').append(configKey.substring(0, configKey.indexOf('('))).append("] ").toString();
return String.format(methodTag.append(format).toString(), args);
} |
* Avoid overhead when logging is disabled.
4befdd0 to
bcc1a47
Compare
|
This PR is now just adding guard around logging. Ran the JMH benchmark https://github.com/schlosna/feign/blob/feature/method-tag-benchmark/benchmark/src/main/java/feign/benchmark/MethodTagBenchmarks.java which shows the existing implementation as faster, so I've reverted that part of this change. |
|
JVM's a mysterious thing, right? :) thanks for the help and the diligence! |
|
Thanks for merging. The results were a bit surprising, but good. There have been a few discussions over the years about moving more of these optimizations into both javac and the JVM itself, see https://bugs.openjdk.java.net/browse/JDK-4059189 and http://markmail.org/message/mrhy6ystcirswhqf , and Java 9's indy string concatenation will likely change the results as well. |
* Avoid overhead when logging is disabled.
* Avoid overhead when logging is disabled.