几款模板引擎的性能对比

参评的几款模板引擎为:  



性能评测考虑以下几个方面:变量输出/循环/分支,这三大类调用构成了普通模板80%以上的功能。 
测试方法为双层循环,输出的中间体是一个空的不执行任何操作的Writer类, 
尽可能的减少模板外的性能影响因素,基本的逻辑伪代码描述如下: 
Java代码   收藏代码
  1. for (int i = 0; i < outerTime; i++) {  
  2.   for (int j = 0; j < innerTime; j++) {  
  3.     testXMLTemplate();  
  4.   }  
  5.   for (int j = 0; j < innerTime; j++) {  
  6.     testVelocityTemplate();  
  7.   }  
  8.   for (int j = 0; j < innerTime; j++) {  
  9.     testCommonTemplate();  
  10.   }  
  11.   for (int j = 0; j < innerTime; j++) {  
  12.     testFreeMarker();  
  13.   }  
  14.   for (int j = 0; j < innerTime; j++) {  
  15.     testSmarty4j();  
  16.   }  
  17.   for (int j = 0; j < innerTime; j++) {  
  18.     testJavaCode();  
  19.   }  
  20. }  


第一步,测试循环输出ascii码表,各模板引擎文件为  

XT:asciitable.xhtml 
Java代码   收藏代码
  1. <div xmlns:c="http://www.xidea.org/ns/template/core">  
  2.   <h1>${name}</h1>  
  3.   <table border="${border}">  
  4.     <tr>  
  5.       <th>&#160;</th>  
  6.       <c:for var="cell" items="${data}">  
  7.       <th>${cell}</th>  
  8.       </c:for>  
  9.     </tr>  
  10.     <c:for var="row" items="${data}">  
  11.     <tr>  
  12.         <th>${row}</th>  
  13.         <c:for var="cell" items="${data}">  
  14.           <td><c:out value="&amp;#x"/>${row}${cell};</td>  
  15.         </c:for>  
  16.     </tr>  
  17.     </c:for>  
  18.   </table>  
  19. </div>  


VT:asciitable.vm 
Java代码   收藏代码
  1. <div>  
  2. <h1>${name}</h1>  
  3. <table border="${border}">  
  4.  <tr>  
  5.   <th>&#160;</th>  
  6. #foreach($cell in $data)  
  7.   <th>${cell}</th>  
  8. #end  
  9.  </tr>  
  10. #foreach($row in $data)  
  11.  <tr>  
  12.   <th>${row}</th>  
  13. #foreach($cell in $data )  
  14.   <td>&#x${row}${cell};</td>  
  15. #end  
  16.  </tr>  
  17. #end  
  18. </table>  
  19. </div>  


CT:asciitable.ct 
Java代码   收藏代码
  1. <div>  
  2. <h1>${name}</h1>  
  3. <table border="${border}">  
  4.  <tr>  
  5.   <th>&#160;</th>  
  6. $for{cell:data}  
  7.   <th>${cell}</th>  
  8. $end  
  9.  </tr>  
  10. $for{row:data}  
  11.  <tr>  
  12.   <th>${row}</th>  
  13. $for{cell:data}  
  14.   <td>&#x${row}${cell};</td>  
  15. $end  
  16.  </tr>  
  17. $end  
  18. </table>  
  19. </div>  


FT:asciitable.ftl 
Java代码   收藏代码
  1. <div>  
  2. <h1>${name}</h1>  
  3. <table border="${border}">  
  4.  <tr>  
  5.   <th>&#160;</th>  
  6. <#list data as cell>  
  7.   <th>${cell}</th>  
  8. </#list>  
  9.  </tr>  
  10. <#list data as row>  
  11.  <tr>  
  12.   <th>${row}</th>  
  13. <#list data as cell>  
  14.   <td>&#x${row}${cell};</td>  
  15. </#list>  
  16.  </tr>  
  17. </#list>  
  18. </table>  
  19. </div>  

Java代码   收藏代码
  1. ST:asciitable.html  
  2. <div>  
  3. <h1>{$name}</h1>  
  4. <table border="{$border}">  
  5.  <tr>  
  6.   <th>&#160;</th>  
  7. {section loop=$data name="cell"}  
  8.   <th>{$cell}</th>  
  9. {/section}  
  10.  </tr>  
  11. {section loop=$data name="row"}  
  12.  <tr>  
  13.   <th>{$row}</th>  
  14. {section loop=$data name="cell"}  
  15.   <td>&#x{$row}{$cell};</td>  
  16. {/section}  
  17.  </tr>  
  18. {/section}  
  19. </table>  
  20. </div>  


JAVA:asciitable.java 
Java代码   收藏代码
  1. package org.jside.tt;  
  2.   
  3. import java.io.Writer;  
  4. import java.util.List;  
  5. import java.util.Map;  
  6.   
  7. public class asciitable implements ICode {  
  8.   
  9.   @Override  
  10.   public void execute(Map<String, Object> context, Writer writer) throws Exception {  
  11.     List<String> data = (List<String>) context.get("data");  
  12.     String name = (String) context.get("name");  
  13.     String border = (String) context.get("border");  
  14.     writer.write("<div>\n<h1>");  
  15.     writer.write(name);  
  16.     writer.write("</h1>\n<table border=\"");  
  17.     writer.write(border);  
  18.     writer.write("\">\n\t<tr>\n\t\t<th>&#160;</th>\n");  
  19.     for (String cell : data) {  
  20.       writer.write("\t\t<th>");  
  21.       writer.write(cell);  
  22.       writer.write("</th>\n");  
  23.     }  
  24.     writer.write("\t</tr>\n");  
  25.     for (String row : data) {  
  26.       writer.write("\t<tr>\n<th>");  
  27.       writer.write(row);  
  28.       writer.write("</th>\n");  
  29.       for (String cell : data) {  
  30.         writer.write("\t\t<td>&#x");  
  31.         writer.write(row);  
  32.         writer.write(cell);  
  33.         writer.write("</td>\n");  
  34.       }  
  35.       writer.write("\t</tr>\n");  
  36.     }  
  37.     writer.write("</table>\n</div>\n");  
  38.   }  
  39.   
  40. }  


在outerTime=100与innerTime=100时,共循环10000次,平均的结果约是: 

=============runing time=============== 
引用
xt:2149 
vt:3499 
ct:72254 
ft:2761 
st:1235 
CODE:1321


第二步,在最内层的循环中多输出一个对象,测试新增输出时的性能影响,最内层的那一行改造如下: 
Java代码   收藏代码
  1. XT:  
  2. <td>${name}:<c:out value="&amp;#x"/>${row}${cell};</td>  
  3. VT:  
  4. <td>${name}:&#x${row}${cell};</td>  
  5. CT:  
  6. <td>${name}:&#x${row}${cell};</td>  
  7. FT:  
  8. <td>${name}:&#x${row}${cell};</td>  
  9. ST:  
  10. <td>{$name}:&#x{$row}{$cell};</td>  
  11. JAVA:  
  12.         writer.write("\t\t<td>");  
  13.         writer.write(name);  
  14.         writer.write(":&#x");  
  15.         writer.write(row);  
  16.         writer.write(cell);  
  17.         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码表,改造如下: 
Java代码   收藏代码
  1. XT:  
  2. <td><c:if test="${(row=='4' &amp;&amp; cell!='0') || (row=='5' &amp;&amp; cell&lt;'B')}"><c:out value="&amp;#x"/>${row}${cell};</c:if><c:else><c:out value="&amp;"/>nbsp;</c:else></td>  
  3. VT:  
  4. <td>#if(($row=="4" && $cell!="0") || ($row=="5" && $cell!="B" && $cell!="C" && $cell!="D" && $cell!="E" && $cell!="F"))&#x${row}${cell};#else&nbsp;#end</td>  
  5. CT:  
  6. <td>$if{(row=="4" && cell!="0") || (row=="5" && cell<"B")}&#x${row}${cell};$else{}&nbsp;$end</td>  
  7. FT:  
  8. <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>&nbsp;</#if></td>  
  9. ST:  
  10. <td>{if ($row==='4' && $cell!=='0') || ($row==='5' && $cell<'B')}&#x{$row}{$cell};{else}&nbsp;{/if}</td>  
  11. JAVA:  
  12.         writer.write("\t\t<td>");  
  13.         if ((row.equals("4") && !cell.equals("0"))  
  14.             || (row.equals("5") && cell.compareTo("B") < 0)) {  
  15.           writer.write("&#x");  
  16.           writer.write(row);  
  17.           writer.write(cell);  
  18.         } else {  
  19.           writer.write("&nbsp;");  
  20.         }  
  21.         writer.write("</td>\n");  

考虑到比较的问题,也可以对整个循环进行优化 
Java代码   收藏代码
  1. for (String row : data) {  
  2.   char cRow = row.charAt(0);  
  3.   writer.write("\t<tr>\n<th>");  
  4.   writer.write(row);  
  5.   writer.write("</th>\n");  
  6.   for (String cell : data) {  
  7.     char cCell = cell.charAt(0);  
  8.     writer.write("\t\t<td>");  
  9.     if ((cRow == '4' && cCell != '0') || (cRow == '5' && cCell < 'B')) {  
  10.       writer.write("&#x");  
  11.       writer.write(row);  
  12.       writer.write(cell);  
  13.     } else {  
  14.       writer.write("&nbsp;");  
  15.     }  
  16.     writer.write("</td>\n");  
  17.   }  
  18.   writer.write("\t</tr>\n");  
  19. }  

在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个数量级 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Beetl相对于其他java模板引擎,具有功能齐全,语法直观,性能超高,开发和维护模板有很好的体验。是新一代的模板引擎。总得来说,它的特性如下: 1、功能完备:同主流的java模板引擎相比,Beetl具有绝大多数功能。适用于各种应用场景,从对响应速度有很高要求的大网站到功能繁多的CMS管理系统都适合。Beetl本身还具有很多独特功能来完成模板编写和维护,这是其他模板引擎所不具有的。 2、非常简单:类似Javascript语法和习俗,只要半小时就能通过半学半猜完全掌握用法。拒绝其他模板引擎那种非人性化的语法和习俗。 3、超高的性能:Beetl 远超过主流java模板引擎性能,如5-6倍于freemarker,2倍于传统jsp技术。而且消耗较低的CPU 4、易于整合:Beetl能很容易的与各种web框架整合,如Spring MVC,JFinal,Struts,Nutz,Jodd,Servlet等。 5、支持模板单独开发和测试,即在MVC架构中,即使没有M和C部分,也能开发和测试模板。 6、扩展和个性化:Beetl支持自定义方法,格式化函数,虚拟属性,标签,和HTML标签。同时Beetl也支持自定义占位符和控制语句起始符号也支持使用者完全可以打造适合自己的工具包。 关于性能: 通过与主流模板引擎Freemarker,Velocity以及JSP对比,Beetl均远高于前面三个,这是因为宏观上,通过了优化的渲染引擎,IO的二进制输出,字节码属性访问增强,微观上,通过一维数组保存上下文,合并静态文本,通过重复使用字节数组来防止java频繁的创建和销毁数组,还使用模板缓存,运行时优化等方法。 独特功能: Beetl有些功能是发展了10多年的模板引擎所不具备的,这些功能非常利于模板的开发和维护,如下: 1、自定义占位符和控制语句起始符号,这有利于减小模板语法对模板的倾入性,比如在html模板中,如果定义控制语句符号是,那么,大部分模板文件都能同过浏览器打开。有的使用者仅仅采用了单个符号@ 以及回车换号作为控制语句起始符号,这又能提高开发效率。 2、可单独测试的模板。无需真正的控制层和模型层,Beetl的模板就可以单独开发和测试。 3、同时支持较为松散的MVC和严格的MVC,如果在模板语言里嵌入计算表达式,复杂条件表达式,以及函数调用有干涉业务逻辑嫌疑,你可以禁止使用这些语法。 4、强大的安全输出,通过安全输出符号!,能在模板变量,变量属性引用,for循环,占位符输出,try-catch中等各个地方提供安全输出,保证渲染正常。 5、模板变量:运行将模板的某一部分输出像js那样赋值个一个变量,稍后再处理。利用模板变量能完成非常复杂的页面布局(简单的布局可使用layout标签函数)。 6、类型推测,能在运行的时候推测模板变量类型,从而优化性能,也可以通过注解的方法显示的说明模板变量属性(这是非必须的,但有助于IDE自动提示功能)。 7、可插拔的设计,错误信息提示,模板引擎缓存机制,模板资源管理,本地调用的安全管理器,严格MVC限制,模板引擎本身都有默认的实现,但又完全可以自定义以适合特定需求。 8、增强的语法,如#ajax局部渲染,for-elsefor, select-case,安全输出符号! 等,这些语法特别适合模板开发。 9、性能超高,具有最快的模板解释引擎,同时,又有较低的CPU消耗。适合各类模板引用,如CMS系统,超高访问量的门户系统。
Freemarker 是一种模板引擎,它允许开发人员使用模板语言来生成文本输出。它是一种非常流行的模板引擎,被广泛用于 Web 应用程序、邮件和 PDF 的生成等领域。下面是 Freemarker 模板引擎与其他工具的对比: 1. Freemarker vs JSP JSP 是 Java 服务器页面的缩写,它允许开发人员将 Java 代码嵌入到 HTML 页面中。与 JSP 不同,Freemarker 模板引擎使用一个独立的模板语言,这使得它更加灵活和易于维护。另外,Freemarker 可以与任何 Java 应用程序一起使用,而不需要一个专门的 Web 容器。 2. Freemarker vs Velocity Velocity 是一个开源的模板引擎,它与 Freemarker 类似,但它的语法更加简单。与 Velocity 不同,Freemarker 模板引擎提供了更多的功能和灵活性,包括模板继承、条件语句和循环语句等功能。此外,Freemarker 模板引擎还支持多个模板文件格式,包括 HTML、XML、JSON 和 CSV 等。 3. Freemarker vs Thymeleaf Thymeleaf 是一个现代化的服务器端 Java 模板引擎,它提供了更加直观的语法和更多的功能。与 Thymeleaf 不同,Freemarker 模板引擎使用一个简单而直观的模板语言,这使得它更容易学习和使用。另外,Freemarker 模板引擎还提供了更高的性能和更好的缓存机制。 总的来说,Freemarker 模板引擎是一个功能强大、灵活且易于使用的模板引擎,它可以与任何 Java 应用程序一起使用,并提供了多种模板文件格式支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值