作者:赵磊
博客:http://elf8848.iteye.com
Struts2、SpringMVC、Servlet(Jsp)性能对比测试。
Servlet的性能应该是最好的,可以做为参考基准,其它测试都要向它看齐,参照它。
做为一个程序员,对于各个框架的性能要有一个基本的认知,便于选型时做出正确的决策。
在测试中发现了什么也不要大喊大叫,因为这些都是Java程序员的基础知识。人人都要了解。
---------------------------------------------------------------------------------------
建议先阅读《你想建设一个能承受500万PV/每天的网站吗? 》一文,了解一些测试的基本概念。在测试开始前就有一个性能好与坏的标准。再用这个标准来检验你程序。
---------------------------------------------------------------------------------------
测试环境说明:
服务器: 4G内存,至强3.0 (4核超线程)CPU,windows 2003
测试机:笔记本 2G内存,p8600 双核CPU,windows XP
网络:100Mb局域网
测试软件:
Jmeter 2.3.4 分配了512M内存
tomcat 6 默认内存大小
---------------------------------------------------------------------------------------
测试配置如下图:其实jmeter还是很弱的,我打开"集合点(synchronizing Timer)","察看结果树","用表格查看结果"中的任何一个都会导致测试结果中的性能下降和小部分请求的响应出错(可能是线程数太多了),所以禁用了。只启用了cookie管理器。
---------------------------------------------------------------------------------------
Tomcat6.0 配置文件的说明 ,做测试之前是要整清楚的。
默认的Server.xml中如下
- <Connector port="8080" maxHttpHeaderSize="8192"
- maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
- enableLookups="false" redirectPort="8443" acceptCount="100"
- connectionTimeout="20000" disableUploadTimeout="true" />
enableLookups
是否允许DNS查询,当web应用程序要通过域名服务器查找机器名转换为IP地址时。会使用DNS查询,需要占用网络,延长较长
maxThreads
Tomcat可创建的最大的线程数,每一个请求须要一个线程来处理,原来的150太小了,我们测试时并发会超过他的。
acceptCount
指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,就是被排队的请求数,超过这个数的请求将拒绝连接。
connnectionTimeout
网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为20000毫秒。
minSpareThreads
Tomcat初始化时创建的线程数
maxSpareThreads
一旦创建的线程中空闲线程超过这个值,Tomcat就会关闭不再需要的socket线程。
注意:maxThreads 设置为500,也就是Tomcat最多同时使用500个线程处理500个并发(服务器CPU不错,500没问题),不要发生排队等待的情况以免影响测试成绩,为下面的压力测试做好准备。
---------------------------------测试开始了-------------------------------------------
测试时服务器CPU使用率 10%
测试时测试机CPU使用率 100%(测试机不行啊,主要是Jmeter的性能一般,又吃内存,测试机p8600双核CPU还是很强的)
每次测试CPU都这样,就统一写这里了。
测试1:JSP页面--2213个请求/秒
100并发,循环100次,共10000个请求,请求一个大小3.34KB的jsp页面。
测试2:JSP页面--1889个请求/秒
100并发,循环100次,共10000个请求,请求一个servlet总控制器,验证权限后(很简单),new一个Action,再转发到一个大小3.34KB的jsp页面。
测试3:HTML页面--2607个请求/秒
100并发,循环100次,共10000个请求,请求一个3.2KB的html页面。
测试4: HTML页面--833个请求/秒
100并发,循环100次,共10000个请求,请求一个13.4KB的html页面。与上面比是只是文件大了一些,把网卡跑满了,网卡成为了性能瓶颈,RPS降了不少!!
测试5: Spring MVC 2012个请求/秒
100并发,循环100次,共10000个请求,请求一个spring3 MVC的action,再转发到一个0.8K的JSP,其内容是简单的html
测试6: Spring MVC 1800-1924个请求/秒
100并发,循环100次,共10000个请求,请求一个spring3 MVC的action,两个参数类型转换为int、Date,再new 一个List,再转发到一个1.3K的JSP,用JSTL标签显示List中的内容。
JSTL标签内容是如下,看来JSTL标签性能还是不错的。
- <c:if test="${empty list}">
- <tr>
- <td align="center">无记录!</td>
- </tr>
- </c:if>
- <c:if test="${not empty list}">
- <tr>
- <th>从 1 开始的迭代计数</th>
- <th>从 0 开始的迭代计数</th>
- <th>产品名称</th>
- </tr>
- <c:forEach items="${list}" var="item" varStatus="s">
- <tr bgcolor=${s.index%2==0?"#E2E2E2":""}>
- <td align="center">${s.count} </td>
- <td align="center">${s.index} </td>
- <td align="center">${item} </td>
- </tr>
- </c:forEach>
- </c:if>
测试7: 访问一张图片(srping方式一) 1997个请求/秒
100并发,循环100次,共10000个请求. 因为我使用了spring3 MVC,拦截/,所以图片不能访问,所以添加了:
- <servlet-mapping>
- <servlet-name>default</servlet-name>
- <url-pattern>*.jpg</url-pattern>
- </servlet-mapping>
走默认的servlet,来访问2.5K的图片
测试8:访问一张图片(srping方式二) 1967个请求/秒
100并发,循环100次,共10000个请求,因为我使用了spring3 MVC,拦截/,所以图片不能访问,所以添加了:
<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>
来访问2.5K的图片,会走spring的可匹配的一个拦截器。
测试9:Struts2 使用官方提供的示例程序(使用了Struts2标签) 几十个请求/秒
100并发,循环1次,没有循环100次,因为strtus2在这次测试中响应太慢了,我等不起了,所以单个url的测试样本从10000降到了100.一共11个url,共1100个样本。
"spring" 使用的就是前面“测试5”的URL,放在这里是为了与strtus2对比的。
"html" 使用的就是前面“测试3”的URL,放在这里是为了与strtus2对比的。
"struts2-1" 使用的是官方自带的示例项目,名称是struts2-blank-2.1.8.1.war
"struts2-2" 使用的是官方自带的示例项目,名称是struts2-showcase-2.1.8.1.war,我在其中随便选了一个action来做测试
"struts2-3" 同上
"struts2-4" 同上
"struts2-5" 同上
"struts2-6" 同上
"struts2-7" 同上
"struts2-8" 同上
"struts2-9" 同上
未对Struts2做优化,使用的都是官方带的示例,Struts2的测试结果不理想,放在这里做一个参考。“struts2-1”是struts2中测试成绩是本次最高的,但也不十分理想。
测试10:Struts2 官方提供的示例程序(使用Struts2标签--s:property) 1192个请求/秒
上一个测试结果糟糕的太离谱了,第二天,想了想又开始重新测试,使用的还是struts2官方提供的struts2-blank-2.1.8.1.war示例。
访问下面的action: http://192.168.0.5/struts2/example/HelloWorld.action ,action内容很简单就是转发到一个JSP。
下图是使用官方示例中默认的action,我没有修改,结果如下图
这里要说一说转发到的jsp中的内容,其中有struts2标签,如下:
- <s:property value="message"/>
- <s:url id="url" action="HelloWorld">
- <s:param name="request_locale">en</s:param>
- </s:url>
- <s:a href="%{url}">English</s:a>
测试11:Struts2 官方提供的示例程序(不使用Struts2标签) 1976个请求/秒--优秀啊
我把“测试10”中的jsp文件内容改了,删除了所有的struts2标签,只输出一行文本,测试结果如下图:
天啊,性能超出我的想像,性能太好了,达到了我的要求。看来一定是struts2标签拖了后腿。
测试12:Struts2 官方提供的示例程序(使用Struts2标签--s:form) 426个请求/秒
为了让现象复现,我把“测试10”中jsp又改了,jsp中换用了其它的struts2标签 ,测试结果如下图:
使用的标签是:
- <s:form action="Login">
- <s:textfield key="username"/>
- <s:password key="password" />
- <s:submit/>
- </s:form>
=====================================================
结论:
struts2框架性能很好,但struts2的标签性能太差了。 要避免使用struts2标签。
Struts2由于采用了 值栈、OGNL表达式、struts2标签库等,会导致性能下降,很严重的下降。如果避免或减少使用这些,性能还是很好的。
Struts2的多层拦截器、多实例action性能都很好,并不是导致性能问题的原因。
注:以上测试都没有数据库,也没有复杂业务,action和jsp中内容很简单,目的就是测试MVC部分的性能。
---------------------------------------------------------------------------------------
其它测试文章:
http://zhaoshg.iteye.com/blog/356231
http://www.iteye.com/topic/679543
MVC框架性能比较
http://wenku.baidu.com/view/148d7e34eefdc8d376ee32ac.html
spring3mvc与struts2比较
http://www.iteye.com/topic/646240
---------------------------------------------------------------------------------------
附:几种标签和框架组合解析数据时候的 性能测试对比
一、 数据
数据通过查询日志表得到数据,共 1302 条数据,将查询出的数据放入一个静态 List 中,保证每次请求的数据相同。
测试页面的元素相同,只是在取数据方式上不同。
二、 测试目标
1、 在 JSP 页面使用 struts2 标签的性能;
2、 在 JSP 页面使用 JSTL 标签的性能;
3、 在 Freemarker 页面使用 struts2 标签的性能;
4、 在 Freemarker 页面使用 JSTL 标签的性能;
5、 在 Freemarker 页面使用其本身的数据加载方式的性能。
三、 加载耗时对比
时间: ms 注:每一次对比都是在同一时间段按同一顺序依次执行下列几种方式
| struts2 | JSTL(C) | Freemarker-struts2 | Freemarker-C | Freemarker |
第一次 | 306 | 58 | 1618 |
| 41 |
第二次 | 202 | 52 | 1643 |
| 39 |
第三次 | 211 | 58 | 2047 |
| 36 |
第四次 | 196 | 49 | 1621 |
| 28 |
第五次 | 218 | 52 | 1607 |
| 40 |
第六次 | 303 | 331 | 1857 |
| 45 |
第七次 | 210 | 50 | 1671 |
| 33 |
第八次 | 311 | 51 | 1699 |
| 47 |
第九次 | 462 | 55 | 2180 |
| 37 |
第十次 | 218 | 46 | 1721 |
| 42 |
平均值 | 263.7 | 80.2 | 1766.4 |
| 38.8 |
去掉最高和最低 | 223.75 | 53.125 | 1547.125 |
| 39.125 |