优化Web应用的性能绝不象有些人想象的那样简单易行它涉及到诸多技术从最简单的HTML代码修改到复杂的EJB改造无不涉及性能问题但有一点是非常清楚的要想找出和解决Web应用的性能瓶颈就必须深入全面地了解信息在Web应用中的流程
改善Web应用的性能不一定要局限于Web应用的Java代码例如有些时候简单地改动一下HTML页面的质量减少其传输频度和数据量就可以有效地提高应用的性能表现有时提高性能的关键却在于修改Web应用的数据库访问部分——这只是Java代码之外影响性能的两个因素其他还有许多因素会影响到Web应用的整体性能表现另一方面就Java程序本身而言其性能优化又可以分成三个领域基本的Java代码优化JSP/Servlet优化EJB优化
一表现层优化
Web应用的最大性能瓶颈常常不在其他地方而在于最基本的网络带宽限制如果你的Web应用也面临这类问题提高性能最简单的办法是减少HTTP传输例如用JavaScript实现客户端编辑功能以减少数据传输次数避免将数据发送到服务器端再执行合法性验证之类的编辑操作
应当采用一切可能措施减少通过网络传输的数据例如你可以要求浏览器缓沖模块化的JavaScript文件在SCRIPT标记的SRC中指定
SCRIPT LANGUAGE=JavaScript SRC=FormChekjs
其他减少网络传输应当注意的地方还包括避免过度使用隐藏域减少超长Cookie值在RADIOCHECKBOX和SELECT域中用代码来替代长长的字符串等等不过在HTML优化方面本文不准备作全面的讨论因为WebSphere应用的开发者一般不会担负设计表现层的责任只要了解下面这个原理就足够了
性能技巧之一尽可能减少HTTP数据传输的总量和频度
二数据库访问
朋友小A对Java的了解极为有限但他却成功地改进了许多WebSphere应用的性能他是怎么做到的呢?原来小A是一个数据库专家他通过优化数据库访问有效地改进了整个应用的性能但对于Java他只是略微了解一些有关JDBC的知识在优化数据库访问时小A做的第一件事情总是检查数据库的设计有时他会建议重新构造数据库的结构(必须指出的是为了提高性能而重新构造数据库结构有时可能使数据库反规格化(DeNormalization)从而带来维护方面的问题)
性能技巧之二规格化(Normalization)数据库结构
小A做的第二件事情是执行数据库分析根据分析结果提出增加某个索引减少某个索引的建议完成这一步骤后小A通常可以让应用有令人满意的性能表现根本不必去查看应用的Java代码
性能技巧之三针对常用的SQL操作建立索引删除多余的索引
有时为了进一步优化应用的性能小A会检查Java(也许应该说是SQL)代码经常找到Java程序没有合理运用PreparedStatement和连接缓沖池的情形只要把Statement类的动态SQL替换成PreparedStatement类的静态SQL从连接池提取SQL连接(而不是直接创建连接)应用的性能将得到显着的改善注意DB UDB(包括其他一些数据库)的PreparedStatement是可调整和配置的
性能技巧之四合理运用PreparedStatement和连接池
进一步分析应用的工作流程之后小A有时会建议批量执行某些SQL命令这样就只需一个对数据库服务器的请求就可以运行大量的SQL命令
性能技巧之五考虑批量执行SQL命令
既然如此小A有时还会指出如果应用中有些SQL命令可以组合成单个事务逻辑那么应该可以用一个存储过程来替代DB UDB的存储过程语言(SPLStored Procedure Language)非常强大如果把数据库操作逻辑从Web应用转移到数据库一般总是对性能有益不过需要注意的是虽然批量执行SQL命令或使用存储过程会提高性能但就象重新构造数据库结构一样有时会带来维护方面的困难
性能技巧之六考虑使用数据库存储过程
检查JDBC代码的时候小A总是留意对象有没有及时正确释放这一点其实很重要
性能技巧之七及时关闭不用的StatementResultSetConnection等对象(但不是在finalize方法内)
三Java代码
前面我们以小A的经验为例探讨了Web应用中数据库访问性能的重要性调整好数据库之后接下来要做的自然是深入分析应用的Java代码从哪里入手呢?你最好使用Java分析工具来找出性能问题的焦点所在优化Java代码的性能是一个艰苦的过程因此一个重要的原则是把精力集中到那些可能引起性能问题的代码上换句话说就是要尊重/规则利用Java分析工具的结果调整带来%性能开销的那%代码
性能技巧之八用Java分析工具清楚地界定性能问题所在
目前市场上已经有许多优秀的Java分析工具例如ejtechnologie的JProfile()Klgroup的Jprobe()以及Intuitive Systems的OptimizeIt()不过不要忘记WebSphere Studio Application Developer(WSAD)本身也集成了一个优秀的分析器有条件的话最好多用几种分析工具分析Java代码
考虑到资金问题你不一定乐意购买昂贵的分析软件但你可以用Java本身的命令行工具生成分析信息例如在JDK 中你可以用下面的命令将TestOrderProcessing类的CPU使用情况保存到javahprof文件java Xrunhprof:cpu=timesformat=afile=javahprof TestOrderProcessing
这种办法的缺点是它提供的信息条理不够清楚比较繁杂也许可以找到一些源代码开放的工具辅助分析但一般不如使用WSAD本身的分析工具或商业化的分析工具方便另外如果你已经了解哪些代码块可能引起性能问题可以通过保存系统时间的方式获得分析信息例如
long startTime = SystemcurrentTimeMillis();
// 执行某些操作
long endTime = SystemcurrentTimeMillis();
基本篇
有人建议稳定性第一速度第二一般而言遵从这个建议是不会错的但这并不妨碍我们在编写代码的同时运用某些已经证实的性能技巧例如我们都知道String类是不可变的连接两个String是一项开销很大操作
性能技巧之九用StringBuffer来连接两个字符串
也许你已经注意到Sun的许多标准Java类是线程安全的这些类内部的同步机制实际上很容易造成性能问题例如Vector类就是一个线程安全的类除非确实要用到同步机制否则使用Vector是不值得的如有可能应当尽量改用非线程安全的类如ArrayList
性能技巧之十只有在必要时才运用线程安全的类
许多人习惯使用Systemoutprintln来输出跟蹤信息但println要占用不少资源所以输出跟蹤信息最好使用专用日志记录框架如IBM的JRas或Apache的Logj
性能技巧之十一用日志记录框架类输出跟蹤信息而不是使用Systemoutprintln
最后一个提高代码性能的简单技巧是清除类里面的调试信息减小类的体积IBM有一个WSAD插件它提供了一个叫做setDebugInfo的任务可以从Ant脚本调用
性能技巧之十二从正式发行的软件中删除调试信息