博客专区 > 闲大赋的博客 > 博客详情
为什么JSP会比Beetl慢
闲大赋 发表于2年前
为什么JSP会比Beetl慢
  • 发表于 2年前
  • 阅读 12407
  • 收藏 135
  • 点赞 29
  • 评论 81

“粉丝福利”_IT在线,精品课程讲解!>>>   

摘要: JSP是预编译成class的,然后模板渲染里比Beetl慢很多,文章从JSP静态文本处理不足,以及JSTL实现低效来说明JSP实际上要比Beetl慢2倍。从客观的基准测试和第三方性能测试也能证明这一点
   许多人都不相信这个事实,作为前端常用渲染技术,JSP比Beetl慢。如果稍微了解这俩种技术的人,会分析:JSP是编译成class的,而Beetl总是解释执行的。JSP肯定会比Beetl快。然而,事实并不是这样,通过了许多性能测试,证明,Beetl还是要快的,如下是TEB模板引擎性能基准测试结果:


可以看出,代表Beetl的绿色的,性能高于代表JSP的黄色大约2倍。

    还有个帖子来自osc:http://my.oschina.net/tangcoffee/blog/303865,压力测试jsp和beetl,证明beetl性能是JSP的2倍,如下是截取的部分数据

   采用jfinal+beetl模板,apache ab压力测试结果

  • Time taken for tests:   0.656 seconds
  • Complete requests:      1000
  • Time per request:       32.813 [ms] (mean)

   未采用beetl,apache ab测试结果:

  • Time taken for tests:   1.297 seconds
  • Complete requests:      1000
  • Time per request:      64.844  [ms] (mean)

    究竟怎么回事情,使得编译执行的JSP执行比解释执行的Beetl慢。基本上来说,Beetl并没有做出超越常规的性能优化,而是JSP本身性能优化不够导致的。


    第一: JSP对静态文本处理的不够好 。如果你看看JSP编译的后的java代码(以Tocmat7为例),你会发现,JSP并没有优化好静态文本输出。如下一个JSP代码
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Test JSP</title>
</head>
<body>
<%
String a = "Test JSP";
%>
<%=a %>
</body>
</html>。

Tomcat7 会编译成为

out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("<meta http-equiv=\"Content-Type\" 
            content=\"text/html; charset=ISO-8859-1\">\r\n");
      out.write("<title>Test JSP</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
String a = "Test JSP";
      out.write('\r');
      out.write('\n');
      out.print(a );
      out.write("\r\n");
      out.write("</body>\r\n");
      out.write("</html>");

    可以看出,对于静态文本,JSP会多次调用out.write方法,而write方法内部,每次调用,都会做flush检测等耗时机制。因此,更好的方式应该是将静态文本合并一次性输出,应该是下面这种会更好点

// 期望JSP的样子
out.write("<html>\r\n<head>\r\n ....<body>\r\n“);
String a = "Test JSP";
out.write("\r\n“);
out.print(a );
out.write("\r\n</body>\r\n</html>");


第二  就算JSP的实现做了如上更改,静态文本处理还有优化空间。这是因为互联网传输的二进制,因此会存在一个将静态文本转成byte[] 输出的过程,这是一个耗费CPU操作的过程,也就是JSP里的write操作,内部还大量的编码,而且,随着JSP一次次渲染,编码是一次一次重复,实验证明,这极大的降低了JSP性能。通过如下伪代码可以验证

public static void main(String[] args)throws Exception {
  String text = "<html>你好中文!你好中文!你好中文!</html>";
  {
   //模拟jsp
   long start = System.currentTimeMillis();
   for(int i=0;i<1000000;i++){
    byte[] bs = text.getBytes("UTF-8");
    write(bs);
   }
   long end = System.currentTimeMillis();
   System.out.println("jsp total="+(end-start));
  }
 
  {
   // 模拟beetl
   long start = System.currentTimeMillis();
   byte[] bs = text.getBytes("UTF-8");   
   for(int i=0;i<1000000;i++){   
    write(bs);
   }
   long end = System.currentTimeMillis();
   System.out.println("beetl total="+(end-start));
  }
 
 }
 
 public static void write(byte[] bs){
 
 }

输出是:

  • jsp total=228
  • beetl total=3

可见Beetl将静态文本预先编码成二进制,会提高性能很多。而通常JSP,总是静态文本多过JSP Code的

第三,JSP在JSTL做的不够完美,也导致性能很差。由于JSP是基于Java语言,语言本身是OO的,很多地方不适合模板场景使用,因此,自然而然采用JSTL来弥补JSP的不足,这也是后来很多项目都基本上采用了JSTL来写模板。然而,JSTL的性能更加有问题。比如下一个简单的JSTL判断

<c:choose>
   <c:when test="${param.newFlag== '1' || param.newFlag== '2'}">  
    <th>1 or 2  <font color="Red">*</font>
   </c:when>  
</c:choose>


在我最初的想象里,我认为jsp至少会编译成如下代码:


//期望JSP能编译成如下代码
if(request.getParameter("newFlag").equals("1")
   ||request.getParameter("newFlag").equals("2")){

    out.print(...)
}

但事实并不是这样,对于如上JSTL,编译成

// 实际上JSP编译的代码
out.write((java.lang.String) 
  org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(
"${param.newFlag== '1' || param.newFlag== '2'}", 
java.lang.String.class, 
(javax.servlet.jsp.PageContext)_jspx_page_context, null, false));

也就是,JSP并没有如预期的预编译成java代码,而是动态解释执行了 test条件,这样,性能不差才怪呢.


   综上所述,JSP之所以在基准测试还是实际的测试,都比Beetl慢不少,是因为他静态文本输出方面没有去做积极的优化。像JSTL那样的的解释执行也极大的拖了JSP后退,而Beetl避免了这些问题。



  



标签: Beetl JSP 性能
共有 人打赏支持
闲大赋
粉丝 789
博文 68
码字总数 52490
作品 7
评论 (81)
台俊峰
抢个沙发
邹义良
79
邹义良
79
南湖船老大
写的不错
Apache2011
有理 、有据……
景公子
好棒\^O^/
乌龟壳
beetl支持编译吗
逝水fox
79
如梦技术
79
灵魂架构师
软文
闲大赋

引用来自“乌龟壳”的评论

beetl支持编译吗

2.0版本取消了编译。都是解释执行,只有少量地方会生成虚拟码执行
jiangwu

引用来自“徐同乐”的评论

软文
+1 怎么着原生也不会差
FoxHu
一直用velocity,不知道beetl相比velocity有哪些区别和优势?
南湖船老大

引用来自“徐同乐”的评论

软文

引用来自“jiangwu”的评论

+1 怎么着原生也不会差
不,原生不代表高性能,原生的性能确实不好
大风厂老板蔡成功
希望出一个规范版本
tinshen
79
iehyou

引用来自“徐同乐”的评论

软文
过就知道那个好,没用过没有发言权。
雪飘寒
jsp做过优化就测试吗
闲大赋

引用来自“雪飘寒”的评论

jsp做过优化就测试吗
什么样的优化?
glacier0315
真赞
×
闲大赋
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: