jte: JTE is slower than regular String.replace approach
Hello, first of all, thanks for the great library.
I made a simple benchmark in order to test JTE performance and seems JTE is much slower than regular String.replace()
at least for simple use cases.
Benchmark:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
public class JTETest {
String primaryColor = "#ffffff";
String templateTxt;
CodeResolver codeResolver = new DirectoryCodeResolver(Path.of("xxx/templates"));
TemplateEngine templateEngine = TemplateEngine.create(codeResolver, ContentType.Plain);
@Setup
public void setup() {
templateTxt = "<!DOCTYPE html>\n"
+ "<html>\n"
+ "<head>\n"
+ "${primaryColor}\n"
+ "</head>\n"
+ "</html>";
}
@Benchmark
public String concat() {
return "<!DOCTYPE html>\n"
+ "<html>\n"
+ "<head>\n"
+ primaryColor
+ "\n"
+ "</head>\n"
+ "</html>";
}
@Benchmark
public String replace() {
return templateTxt.replace("${primaryColor}", primaryColor);
}
@Benchmark
public String templateEngine() {
TemplateOutput output = new StringOutput();
templateEngine.render("replace_test.jte", primaryColor, output);
return output.toString();
}
}
replace_test.jte:
@param String primaryColor
<!DOCTYPE html>
<html>
<head>
${primaryColor}
</head>
</html>
Result:
Benchmark Mode Cnt Score Error Units
JTETest.concat avgt 5 25.720 ± 2.108 ns/op
JTETest.replace avgt 5 75.095 ± 8.815 ns/op
JTETest.templateEngine avgt 5 2867.906 ± 183.810 ns/op
For the large template 1kb and many replacements, JTE is still slower ~30%. Is that expected?
In theory, if the template doesn’t have any control flow, it could be compiled to String concat pattern:
“<head>” + primaryColor + “</head>”, where OptimizeStringConcat
kicks in. That should make it even faster than regular String.replace
pattern. WDYT?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 16 (8 by maintainers)
Commits related to this issue
- #23 Add JMH benchmark to see difference between TemplateOutput and direct StringBuilder usage. — committed to casid/jte by casid 4 years ago
@doom369 will do that then! And I think it’s a good choice if simple
String.replace
is all that is needed to not add an additional dependency.Thanks for posting the benchmark and all the insights on
String
performance 😃@casid for Java 8 and below it was -XX:+OptimizeStringConcat. Since Java 9 it’s StringConcatFactory. Checkout this JEP - http://openjdk.java.net/jeps/280 it has a lot of interesting info.
Inlining is possible, however, the resulting concatenation won’t be optimized, because it should be chaining calls pattern
.append("tag").append(param)
otherwise JIT doesn’t optimize it. In the case of StringOutput the result will be:those code patterns are not optimized.