转自:http://my.oschina.net/xiandafu/blog/475740

JSP是预编译成class的,然后模板渲染里比Beetl慢很多,文章从JSP静态文本处理不足,以及JSTL实现低效来说明JSP实际上要比Beetl慢2倍,FreeMarker比Beetl慢6倍多。从客观的基准测试和第三方性能测试也能证明这一点。

许多人都不相信这个事实,作为前端常用渲染技术,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代码
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  5. <title>Test JSP</title>
  6. </head>
  7. <body>
  8. <%
  9. String a = "Test JSP";
  10. %>
  11. <%=a %>
  12. </body>
  13. </html>

Tomcat7 会编译成为

  1. out.write("<html>\r\n");
  2. out.write("<head>\r\n");
  3. out.write("<meta http-equiv=\"Content-Type\"
  4. content=\"text/html; charset=ISO-8859-1\">\r\n");
  5. out.write("<title>Test JSP</title>\r\n");
  6. out.write("</head>\r\n");
  7. out.write("<body>\r\n");
  8. String a = "Test JSP";
  9. out.write('\r');
  10. out.write('\n');
  11. out.print(a );
  12. out.write("\r\n");
  13. out.write("</body>\r\n");
  14. out.write("</html>");

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

  1. // 期望JSP的样子
  2. out.write("<html>\r\n<head>\r\n ....<body>\r\n“);
  3. String a = "Test JSP";
  4. out.write("\r\n“);
  5. out.print(a );
  6. out.write("\r\n</body>\r\n</html>");
第二  就算JSP的实现做了如上更改,静态文本处理还有优化空间。这是因为互联网传输的二进制,因此会存在一个将静态文本转成 byte[] 输出的过程,这是一个耗费CPU操作的过程,也就是JSP里的write操作,内部还大量的编码,而且,随着JSP一次次渲染,编码是一次一次重复,实验 证明,这极大的降低了JSP性能。通过如下伪代码可以验证
  1. public static void main(String[] args)throws Exception {
  2. String text = "<html>你好中文!你好中文!你好中文!</html>";
  3. {
  4. //模拟jsp
  5. long start = System.currentTimeMillis();
  6. for(int i=0;i<1000000;i++){
  7. byte[] bs = text.getBytes("UTF-8");
  8. write(bs);
  9. }
  10. long end = System.currentTimeMillis();
  11. System.out.println("jsp total="+(end-start));
  12. }
  13.  
  14. {
  15. // 模拟beetl
  16. long start = System.currentTimeMillis();
  17. byte[] bs = text.getBytes("UTF-8");
  18. for(int i=0;i<1000000;i++){
  19. write(bs);
  20. }
  21. long end = System.currentTimeMillis();
  22. System.out.println("beetl total="+(end-start));
  23. }
  24. }
  25.  
  26. public static void write(byte[] bs){
  27. }

输出是:

  1. jsp total=228
  2. beetl total=3
可见Beetl将静态文本预先编码成二进制,会提高性能很多。而通常JSP,总是静态文本多过JSP Code的。
第三,JSP在JSTL做的不够完美,也导致性能很差。由于JSP是基于Java语言,语言本身是OO的,很多地方不适合模板场景使用,因此,自然而然采用JSTL来弥补JSP的不足,这也是后来很多项目都基本上采用了JSTL来写模板。然而,JSTL的性能更加有问题。比如下一个简单的JSTL判断
  1. <c:choose>
  2. <c:when test="${param.newFlag== '1' || param.newFlag== '2'}">
  3. <th>1 or 2 <font color="Red">*</font>
  4. </c:when>
  5. </c:choose>

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

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

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

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

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

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

为什么JSP会比Beetl慢的更多相关文章

  1. Beetl 3中文文档 转载 http://ibeetl.com/guide/

    Beetl作者:李家智(闲大赋) <xiandafu@126.com> 1. 什么是Beetl 广告:闲大赋知识星球,付费会员 Beetl( 发音同Beetle ) 目前版本是3.0.7, ...

  2. Beetl2.2使用说明书20151201

    李家智<xiandafu@126.com> Table of Contents 1. 什么是Beetl 2. 基本用法 2.1. 从GroupTemplate开始 2.2. 模板基础配置 ...

  3. java开源模板引擎

      Velocity  Velocity是一个基于java的模板引擎(template engine).它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义 ...

  4. Jsp与beetl的比较

    首先介绍一下模板引擎的概念,是为了使用户界面与业务数据分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎,就会生成一个标准的html文档. Jsp全名是JavaServer Page,中文名叫 ...

  5. beetl 配置多视图解析器

    如下配置,指定了三个视图解析器,一个用于beetl页面渲染,一个用于cms,采用了beetl技术,另外一个一些遗留的页面采用jsp <bean name="beetlConfig&qu ...

  6. 2019-04-18 Beetl模板学习

    1. beetl的安装 使用maven: <dependency> <groupId>com.ibeetl</groupId> <artifactId> ...

  7. 基于jeesite的cms系统(四):使用Beetl模版引擎在后端渲染数据

    一.Beetl简介 1. 什么是Beetl Beetl目前版本是2.9.3,相对于其他java模板引擎,具有功能齐全,语法直观,性能超高,以及编写的模板容易维护等特点.使得开发和维护模板有很好的体验. ...

  8. beetl模板的${!}用法

    转自:http://ibeetl.com/guide/#beetl 2.20. 安全输出 安全输出是任何一个模板引擎必须重视的问题,否则,将极大困扰模板开发者.Beetl中,如果要输出的模板变量为nu ...

  9. Beetl使用注意事项

    1.如果表达式跟定界符或者占位符有冲突,可以在用 “\” 符号 @for(user in users){ email is ${user.name}\@163.com @} ${[1,2,3]} // ...

随机推荐

  1. cookie注入原理详解(一)

    那我们还是围绕以下几个问题来看看cookie注入: 1.什么是cookie注入? 2.为什么要cookie注入? 3.怎样cookie注入? 1.什么是cookie注入? ♦cookie注入的原理是: ...

  2. YouCompleteMe自动补全的安装配置与使用

    1 下载 git clone --recursive git://github.com/Valloric/YouCompleteMe 如果执行该命令没报错, 就ok了. 但是中途有可能会断掉, 可以 ...

  3. Educational Codeforces Round 47 D

    Let's call an undirected graph $G=(V,E)$ relatively prime if and only if for each edge $(v,u)∈E$ $GC ...

  4. [翻译]将智能指针用于C++的类成员

    http://stackoverflow.com/questions/15648844/using-smart-pointers-for-class-members Question: I'm hav ...

  5. 安装基础版的kinetic

    没有gui工具 sudo apt-get install ros-kinetic-ros-base

  6. css3 抖动

    1. html <div id="wrapper"> <section> <p class="shake freez shake-hard& ...

  7. EF大数据批量添加性能问题

    前几天做一个批量发消息的功能,因为要向消息表中批量写入数据,用的EF框架的插入方法:不用不知道,一用吓一跳:就10000条数据就耗时好几分钟,对应追求用户体验的我来说这是极不能容忍的,后来改为拼接SQ ...

  8. Rails 5 Test Prescriptions(everday Rspectest作者推荐) 目录 1-3章

    总文档连接: RSpec.info/documentation/ 如何使用TDD 和 自动化测试来建立一个Rails app. TDD让你用测试来探索代码的设计.你将学习可利用的工具,并学习用什么工具 ...

  9. Lightoj-1220

    https://vjudge.net/problem/LightOJ-1220 求x=bp中最大的p,x可能为负数. 因数分解,x=p1x1*p2x2*...*pnxn x=(p1x1'*p2x2'* ...

  10. Hibernate批量处理数据、[HQL连接查询]

    一.批量处理操作 批量处理数据是指在一个事务场景中处理大量数据.在应用程序中难以避免进行批量操作,Hibernate提供了以下方式进行批量处理数据: (1)使用HQL进行批量操作 数据库层面 (2)使 ...