文档章节

为什么JSP会比Beetl慢

闲大赋
 闲大赋
发布于 2015/07/07 16:16
字数 1211
阅读 13581
收藏 138
   许多人都不相信这个事实,作为前端常用渲染技术,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避免了这些问题。



  



© 著作权归作者所有

共有 人打赏支持
闲大赋

闲大赋

粉丝 1176
博文 95
码字总数 88056
作品 10
西城
架构师
私信 提问
加载中

评论(81)

lifetime
lifetime
beetl 用了快1年了,真心话还是不错的,从我使用jsp+jstl(3年),后来使用velocity(2年)的感受来说,beetl好多了,如果把beetl当作一个产品来看,它的用户体验相当不错,产品也是良心,作者也是在很用心的维护。我不是水手,一个真实的用户。 只是后面有一次设计开发微商城时,因为某个场景特殊,想要个类似xml cdata注释的功能(第一次只渲染出beetl纯文本脚本,第二次渲染时才想要解析)暂时没有,后来通过2个渲染器设置2种不同的定界符来解决的问题。
闲大赋
闲大赋

引用来自“HustSteven”的评论

我简单的理解成Beetle的原理和velocity类似?
不一样地方很多,可以看官网文档,再对比velocity
HustSteven
HustSteven
我简单的理解成Beetle的原理和velocity类似?
高高果实
79
红薯的小黄瓜
红薯的小黄瓜

引用来自“双城记”的评论

其实现在对于web应用来说,性能瓶颈一般出现在磁盘IO、并发、数据库上边,模板性能差距基本可以忽略不计。个人觉得现代模板引擎框架首先应该解决的是模板开发的效率问题和易用性问题。jsp越写越烦躁主要是因为很容易把不必要的逻辑加入到模板中去,一堆的C:IF看着就头疼
<%if(1==1){%> 这样写是不是就不头疼了? <%}%>
闲大赋
闲大赋

引用来自“StoneLee”的评论

求beetl入门教程
http://ibeetl.com/guide/ 第一章,第二章第一节
S
StoneLee
求beetl入门教程
跟猪谈理想
跟猪谈理想

引用来自“Sartner”的评论

引用来自“专治各种BUG”的评论

没啥用 需要性能的苛刻的用lua渲染 或者全静态页面 不需要性能的就JSP 大家都会用。所以这玩意真是然并暖,性能瓶颈都不在渲染上。。
一语道破

就是这个意思。
Most_Gust
Most_Gust
支持一下,一直在用
原来如此
原来如此

引用来自“台俊峰”的评论

抢个沙发
beetl 和 shrio 结合

shrio 提供有jsp 标签,供在jsp 里使用,如果想在beetl中使用,有俩种方法, 一是beetl支持集成jsp页面,所以你可以在在jsp里使用shrio标签 另外,beetl 使用自定义函数写了shiro tag功能,你...

闲大赋
2013/07/08
0
4
Nutz 和 Beetl 插件小工具 NutzCodeInsight V1.5 发布

NutzCodeInsight 在 Nutz Action Module 中点击 @Ok 前面的jsp图标即可快速打开或切换至已经打开的jsp文件 支持beetl,jsp模版中携带${}变量的资源文件的快速定位 idea插件仓库https://plugi...

凋花丶叶落
2018/01/04
881
5
J2EE Preview 和 Tomecat 服务器对Jsp的支持有什么区别?

项目是在eclipse 自带的 J2EE Preview 服务 运行的,之前一直用beetl模板取值,使用html页面。最近想要兼容使用jsp模板,导入了jstl 及jstl支持的包,jstl标签可以使用,问题在于用el表达式取...

沈文龙
2016/12/01
217
0
如何现实servlet的单线程模式?

网上朋友的回答是加入<%@ page isThreadSafe=”false”%>这条命令。天啊,我晕!这是什么命令?是jsp的命令啊,怎么会加入到servlet中呢?当然了,jsp的运行实质是servlet机制,这条命令是j...

零度的魚
2014/01/01
0
0
springmvc不能拦截到.jsp后缀的文件吗

在web.xml里的springmvc前端控制器. 如果配置*.do的话, springmvc只会解析.do结尾的路径去映射和适配controller中的方法, 而直接访问.jsp后缀(包括图片.js等静态资源)的页面会正常显示,所以拦...

初来乍到_
2016/11/29
1K
3

没有更多内容

加载失败,请刷新页面

加载更多

告别2018

今天中午从喵喵家回来之后,倒头就睡到下午4点了。可能是之前透支的身体,在我放松下来后,开始觉得疲惫了,所以最近估计会进入嗜睡期。醒来之后,拿了包花生,开了瓶低糖菊花茶,听着网易云...

七木网络科技
9分钟前
0
0
MySql数据库分表分区实践

1. 背景 —— 公司物联网项目 海量设备通过物联网服务接入云端,设备每30s上报一次自身数据(以下称为动态数据)。 物联网服务将设备上报的数据转发给数据处理网关,由数据入库网关执行批量入...

吴伟祥
21分钟前
0
0
大表关联走hash优化

大表关联走hash? 案例: ---- 反正我执行过1个多小时,没有跑完 SELECT a.id AS order_id ,b.s_id AS bill_id, d.id AS sub_order_id, d.deal_oper_id FROM EM_ORDER PARTITION(EM_ORDER_20......

hnairdb
34分钟前
0
0
MySQL查询执行

当我们希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的。一旦理解了这一点,很多查询优化工作实际上就是遵循一些原则让优化器能够按照预想的合理方式...

问题终结者
今天
1
0
CDH5动静态资源池配置与回滚

关于动态 静态资源池的配置以前都有提过,可以从以下几篇了解: YARN动态资源池配置案例 https://yq.aliyun.com/ziliao/346856# Hadoop YARN配置参数剖析(4)—Fair Scheduler相关参数 Hadoop...

hblt-j
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部