锁定老帖子 主题:几款模板引擎的性能对比
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-12-12
最后修改:2008-12-12
allskystar
原作者,参评的几款模板引擎为:
性能评测考虑以下几个方面:变量输出/循环/分支,这三大类调用构成了普通模板80%以上的功能。 测试方法为双层循环,输出的中间体是一个空的不执行任何操作的Writer类, 尽可能的减少模板外的性能影响因素,基本的逻辑伪代码描述如下: 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(); } } 第一步,测试循环输出ascii码表,各模板引擎文件为 XT:asciitable.xhtml <div xmlns:c="http://www.xidea.org/ns/template/core"> <h1>${name}</h1> <table border="${border}"> <tr> <th> </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> <h1>${name}</h1> <table border="${border}"> <tr> <th> </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> <h1>${name}</h1> <table border="${border}"> <tr> <th> </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> <h1>${name}</h1> <table border="${border}"> <tr> <th> </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> <h1>{$name}</h1> <table border="{$border}"> <tr> <th> </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>\n<h1>"); writer.write(name); writer.write("</h1>\n<table border=\""); writer.write(border); writer.write("\">\n\t<tr>\n\t\t<th> </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"); } } 在outerTime=100与innerTime=100时,共循环10000次,平均的结果约是: =============runing time=============== 引用 xt:2149
vt:3499 ct:72254 ft:2761 st:1235 CODE:1321 第二步,在最内层的循环中多输出一个对象,测试新增输出时的性能影响,最内层的那一行改造如下: 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"); 在outerTime=100与innerTime=100时,共循环10000次,平均的结果约是: =============runing time=============== 引用 xt:3549
vt:4748 ct:103453 ft:4251 st:1750 CODE:1811 第三步,测试分支判断对整体性能的影响,在最内层的循环中输出前加一个分支控制,使它仅输出A-Z对应的ASCII码表,改造如下: 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"); 考虑到比较的问题,也可以对整个循环进行优化 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"); } 在outerTime=100与innerTime=100时,共循环10000次,平均的结果约是: =============runing time=============== 引用 xt:3498
vt:2422 ct:153280 ft:7124 st:1142 CODE:1027(优化后940) 结论: ST在三种常见的模板操作中的表现均极其优秀,除了条件处理效率略低于直接书写的JAVA代码,其它情况下与直接书写JAVA代码效率完全一致,而且在三种操作中,总的执行开销差异非常小。 XT在分支的处理中考虑与JS兼容带来了额外开销,但总体性能仍然占优,只是如果需要过多的XML转义可能影响阅读 FT在分支测试中表现差的原因应该是写法不是最优的,总体来说,性能与VT不相上下 CT的表现最差,在各项操作中均比其它的引擎慢了1-2个数量级 有关的测试代码可以在http://templatetest.googlecode.com/svn/trunk/获得 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-12-12
很好,nnd,刚在velocity上大规模并发测试上碰到性能问题,marge方法效率低,正好换st试试。
|
|
返回顶楼 | |
发表时间:2008-12-12
性能是一个方面,楼主能不能从功能上再对比一下?
不了解Smarty4j,不知道能不能代替Freemarker的功能呢? |
|
返回顶楼 | |
发表时间:2008-12-12
性能只要在一个数量级上,细微的差距并不重要,毕竟web服务器出现瓶颈的可能性不高.
虽然功能对比往往更有价值.但是没有客观的评判标准,是非太多.呵呵. 有空再总结总结,共享一下. |
|
返回顶楼 | |
发表时间:2008-12-12
看了这几个模板引擎的语法,发现XT正是我一直想要的,语法类似JSTL,简单明了,体积小。CT语法也是挺不错的,但是对我来说,它的首要缺点就是扩展的功能太多,库文件比较庞大。
|
|
返回顶楼 | |
发表时间:2008-12-12
xuyao 写道 很好,nnd,刚在velocity上大规模并发测试上碰到性能问题,marge方法效率低,正好换st试试。
不知道你做什么大型应用, 一天50亿PV的? 就我知道的, 不少大站点都是VELOCITY做的。 |
|
返回顶楼 | |
发表时间:2008-12-12
这样改来改去,太麻烦了,我就用过vt,ft
最后还是发现ft的功能更强大些,不知道st如何,如果好用了,以后换着试试,st莫非是从php的smarty过来的? |
|
返回顶楼 | |
发表时间:2008-12-13
看来好像还要测试js模板,
也测试测试偶的jCT吧。 |
|
返回顶楼 | |
发表时间:2008-12-13
习惯用JSP了
|
|
返回顶楼 | |
发表时间:2008-12-13
VELOCITY 我们用这个
生成的代码量也很大还没遇到什么问题 |
|
返回顶楼 | |