Several of the template engines that are participating are:
Xmltemplate (XT)
Velocity (VT)
Commontemplate (referred to as CT)
Freemarker ("FT")
SMARTY4J (referred to as ST)
Direct Java code
The result units for all of the following evaluations are MS
Performance evaluation Consider the following aspects: variable output/loop/branch, these three categories of calls constitute a Normal template more than 80% of the function.
The test method is a double loop, the output intermediate is an empty writer class that does not perform any operation,
As much as possible to reduce the performance impact factors outside the template, the basic logic pseudo-code is described as follows:
for (int i = 0; i < outertime; i++) {
for (int j = 0; J < Innertime; J + +) {
Testxmltemplate ();
}
for (int j = 0; J < Innertime; J + +) {
Testvelocitytemplate ();
}
for (int j = 0; J < Innertime; J + +) {
Testcommontemplate ();
}
for (int j = 0; J < Innertime; J + +) {
Testfreemarker ();
}
for (int j = 0; J < Innertime; J + +) {
Testsmarty4j ();
}
for (int j = 0; J < Innertime; J + +) {
Testjavacode ();
}
}
The first step, the test loop output ASCII code table, each template engine file is
XT:asciitable.xhtml
<!--<! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 strict//en" "Http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
<div xmlns:c= "#core";
<table border= "${border}";
<tr>
<th>& #160; </th>
<c:for var= "cell" items= "${data}";
<th >${cell}</th>
</c:for>
</tr>
<c:for var= "Row" items= "${data}";
<tr>
<th>${row}</th>
<c:for var= "cell" items= "${data}";
< Td><c:out value= "& #x"/>${ROW}${CELL};</TD>
</c:for>
</tr>
</c:for>
</table>
</div>
VT:asciitable.vm
<div>
<table border= "${border}" >
<tr>
<th>& #160;</th>
#foreach ($cell in $data)
<th>${cell}</th>
#end
</tr>
#foreach ($row in $data)
<tr>
<th>${row}</th>
#foreach ($cell in $data)
<td>& #x ${row}${cell};</td>
#end
</tr>
#end
</table>
</div>
CT:asciitable.ct
<div>
<table border= "${border}" >
<tr>
<th>& #160;</th>
$for {Cell:data}
<th>${cell}</th>
$end
</tr>
$for {Row:data}
<tr>
<th>${row}</th>
$for {Cell:data}
<td>& #x ${row}${cell};</td>
$end
</tr>
$end
</table>
</div>
FT:ASCIITABLE.FTL
<div>
<table border= "${border}";
<tr>
<th>& #160; </th>
< #list data as Cell>
<th>${cell }</th>
</#list;
</tr>
< #list data as Row>
<tr>
<th>${row}</th>
< #list data as Cell>
<td>& #x ${row}${cell};</td>
</#list;
</tr>
</#list;
</table>
</div>
ST:asciitable.html
<div>
<table border= "{$border}" >
<tr>
<th>& #160;</th>
{section loop= $data name= "Cell"}
<th>{$cell}</th>
{/section}
</tr>
{section loop= $data name= "Row"}
<tr>
<th>{$row}</th>
{section loop= $data name= "Cell"}
<td>& #x {$row} {$cell};</td>
{/section}
</tr>
{/section}
</table>
</div>
JAVA:asciitable.java
Package org.jside.tt;
Import Java.io.Writer;
Import java.util.List;
Import Java.util.Map;
public class Asciitable implements ICode {
@Override
public void execute (map<string, object> context, writer writer) throws Exception {
list<string> data = (list<string>) context.get ("Data");
String name = (string) context.get ("name");
String border = (string) context.get ("border");
Writer.write ("<div>/nWriter.write (name);
Writer.write ("Writer.write (border);
Writer.write ("/" >/n/t<tr>/n/t/t<th>& #160; </th>/n ");
for (String Cell:data) {
Writer.write ("/t/t<th>");
Writer.write (cell);
Writer.write ("</th>/n");
}
Writer.write ("/t</tr>/n");
for (String Row:data) {
Writer.write ("/t<tr>/n<th>");
Writer.write (row);
Writer.write ("</th>/n");
for (String Cell:data) {
Writer.write ("/t/t<td>& #x");
Writer.write (row);
Writer.write (cell);
Writer.write ("</td>/n");
}
Writer.write ("/t</tr>/n");
}
Writer.write ("</table>/n</div>/n");
}
}
In outertime=100 and innertime=100, the total cycle is 10,000 times, the average result is:
=============runing time===============
xt:2149
vt:3499
ct:72254
ft:2761
st:1235
code:1321
The second step is to output an object in the most inner loop and test the performance impact of the new output, and the most inner line is transformed as follows:
Xt:
<td>${name}:<c:out value= "& #x"/>${row}${cell};</td>
Vt:
<td>${name}:& #x ${row}${cell};</td>
Ct:
<td>${name}:& #x ${row}${cell};</td>
FT:
<td>${name}:& #x ${row}${cell};</td>
St:
<td>{$name}:& #x {$row} {$cell};</td>
Java:
Writer.write ("/t/t<td>");
Writer.write (name);
Writer.write (":& #x");
Writer.write (row);
Writer.write (cell);
Writer.write ("</td>/n");
In outertime=100 and innertime=100, the total cycle is 10,000 times, the average result is:
=============runing time===============
xt:3549
vt:4748
ct:103453
ft:4251
st:1750
code:1811
The third step, the Test branch judgment on the overall performance of the impact, in the most inner loop output before adding a branch control, so that it only output a-Z corresponding ASCII code table, the transformation is as follows:
Xt:
<td><c:if test= "${(row== ' 4 ' && cell!= ' 0 ') | | (row== ' 5 ' && cell< ' B ')} "><c:out value=" & #x "/>${row}${cell};</c:if><c:else><c:out value=" & " />nbsp;</c:else></td>
Vt:
<td> #if ($row = = "4" && $cell! = "0") | | ($row = = "5" && $cell! = "B" && $cell! = "C" && $cell! = "D" && $cell! = "E" && $cell! = "F" ) & #x ${row}${cell}; #else #end </td>
Ct:
<td> $if {(row== "4" && cell!= "0") | | (row== "5" && cell< "B")} & #x ${row}${cell}; $else {} $end </td>
FT:
<td>< #if (row?string== "4" && cell?string!= "0") | | (row?string== ' 5 ' && cell?string!= ' B ' && cell?string!= ' C ' && cell?string!= ' D ' && cell? string!= ' E ' && cell?string!= ' F ') >& #x ${row}${cell};< #else > </#if ></td>
St:
<td>{if ($row = = = ' 4 ' && $cell!== ' 0 ') | | ($row = = = ' 5 ' && $cell < ' B ')} & #x {$row} {$cell}; {else} {/if}</td>
Java:
Writer.write ("/t/t<td>");
if ((Row.equals ("4") &&!cell.equals ("0")
|| (Row.equals ("5") && Cell.compareto ("B") < 0)) {
Writer.write ("& #x");
Writer.write (row);
Writer.write (cell);
} else {
Writer.write (" ");
}
Writer.write ("</td>/n");
The entire cycle can also be optimized, considering the problem of comparison
for (String Row:data) {
Char CRow = row.charat (0);
Writer.write ("/t<tr>/n<th>");
Writer.write (row);
Writer.write ("</th>/n");
for (String Cell:data) {
Char Ccell = cell.charat (0);
Writer.write ("/t/t<td>");
if ((CRow = = ' 4 ' && ccell! = ' 0 ') | | (CRow = = ' 5 ' && Ccell < ' B ')) {
Writer.write ("& #x");
Writer.write (row);
Writer.write (cell);
} else {
Writer.write (" ");
}
Writer.write ("</td>/n");
}
Writer.write ("/t</tr>/n");
}
In outertime=100 and innertime=100, the total cycle is 10,000 times, the average result is:
=============runing time===============
xt:3498
vt:2422
ct:153280
ft:7124
st:1142
code:1027 (optimized 940)
Conclusion:
ST's performance in three common template operations is excellent, except that the conditional processing efficiency is slightly lower than that of the directly written Java code, and in other cases it is fully consistent with the direct writing of Java code, and in three operations, the total execution overhead varies very little.
XT considers the additional overhead of JS compatibility in the processing of branches, but overall performance is still superior, but if excessive XML escaping is required it may affect reading
The reason why FT performs poorly in branch testing should be that it is not optimal, and that overall performance is comparable to VT
CT has the worst performance and is 1-2 slower than other engines in every operation.
The relevant test code can be obtained at http://templatetest.googlecode.com/svn/trunk/
Performance evaluation of several Java template engines