博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么JSP会比Beetl慢
阅读量:4360 次
发布时间:2019-06-07

本文共 3220 字,大约阅读时间需要 10 分钟。

转自: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: ,压力测试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"%>
Test JSP<%String a = "Test JSP";%><%=a %>。

Tomcat7 会编译成为

out.write("\r\n");      out.write("\r\n");      out.write("
\r\n"); out.write("Test JSP\r\n"); out.write("\r\n"); out.write("\r\n");String a = "Test JSP"; out.write('\r'); out.write('\n'); out.print(a ); out.write("\r\n"); out.write("\r\n"); out.write("");

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

// 期望JSP的样子out.write("\r\n\r\n ....\r\n“);String a = "Test JSP";out.write("\r\n“);out.print(a );out.write("\r\n\r\n");
第二  就算JSP的实现做了如上更改,静态文本处理还有优化空间。这是因为互联网传输的二进制,
因此会存在一个将静态文本转成 byte[] 输出的过程,这是一个耗费CPU操作的过程,也就是JSP里的write操作,内部还大量的编码,而且,随着JSP一次次渲染,编码是一次一次重复,实验 证明,这极大的降低了JSP性能。通过如下伪代码可以验证
public static void main(String[] args)throws Exception {  String text = "你好中文!你好中文!你好中文!";  {   //模拟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判断
1 or 2
*

在我最初的想象里,我认为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避免了这些问题。

转载于:https://www.cnblogs.com/digdeep/p/4631520.html

你可能感兴趣的文章
CSS简介
查看>>
常用三大软件评价1
查看>>
MVC各层介绍使用---初步理解
查看>>
单例对象的创建与销毁
查看>>
知识点关键词(记录一下)
查看>>
国际结算业务
查看>>
嵌套循环概念
查看>>
C# 生成订单号的几种方式
查看>>
IOS开发札记
查看>>
1.2.2 OSI参考模型 上
查看>>
centos服务器设置代理上网的方法
查看>>
Spring入门教程:通过MyEclipse开发第一个Spring项目
查看>>
【转】你可能不知道的Shell
查看>>
廖雪峰Java1-2程序基础-1基本结构
查看>>
golang下的grpc
查看>>
1. 自动化运维系列之Cobbler自动装机
查看>>
ASP.NET MVC Model绑定(二)
查看>>
一步一步写算法(之hash表)
查看>>
漫谈并发编程(一) - 并发简单介绍
查看>>
JDBC连接MySQL数据库及演示样例
查看>>