转自: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代码
<%@ page language="java" contentType="text/html; charset=UTF-8" 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避免了这些问题。

为什么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. Linux内核分析06

    进程的描述和进程的创建 一,进程的描述 进程控制块PCB——task_struct (进程描述符),为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. struc ...

  2. 【安装】ES的安装过程

    1.安装ES 首先我们需要去官网下载安装包  官方下载地址 下载后不需要编译,直接解压 解压后结构是这样的(2.5以上版本会有plugins目录,没有的需要手动创建) 方式一: 创建一个es用户(因为 ...

  3. Gym 101246J Buoys(三分查找)

    http://codeforces.com/gym/101246/problem/J 题意: 给定x轴上的n个点的坐标,按顺序从左到右给出,现在要使得每个点的间距相同,可以移动每个点的坐标,但是不能改 ...

  4. 前端工程化 - npm

    什么是npm npm的全称Node Package Manager,npm原先只是作为nodejs的包管理工具,然而随着前端社区的发展,如今npm不仅是nodejs的包管理工具,还是前端js的包管理工 ...

  5. Uva 11178 Morley's Theorem 向量旋转+求直线交点

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=9 题意: Morlery定理是这样的:作三角形ABC每个 ...

  6. bzoj 1799: [Ahoi2009]self 同类分布 数位dp

    1799: [Ahoi2009]self 同类分布 Time Limit: 50 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Descripti ...

  7. ssh 指定ssh端口号

    ssh -p higgs@192.168.43.1

  8. vue 脚手架(二,项目依赖说明 package.json)

    本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 继续上一篇, 上一篇讲了 vue ...

  9. subllime的插件使用

    1.emmet快速使用的方法. html:xt 然后按下tab快速的生成一个html文档. 生成10个div----- div*10 div->ul->li->a->img 写 ...

  10. hdu4965矩阵快速幂

    这题不能直接按常规做啊,因为数组根本就开不下,转换思维A(B*A)^(n*n-1)B 这样的话数组B*A就是10*10了,然后快速幂就行了 刚开始数组都开小了,tle,还找了半天bug...还有就是定 ...