沈宫新 2012-06-26
一.标识(注释)的优化
网站在开发上往往容易出现这样两种情况:一种是代码过于紧密,其中包含大量注释信息和排版空白,一种就是代码太过宽松,其中不但包含了编辑器自动生成的标识语言及大量缩排空白,而且包含了编辑器常用来控制文件结构的特定注释,甚至还有冗余或无用的标识或代码。象这样的代码是不适合传输的。我们可以通过下面一些安全有效的途径来减小文件的大小:
1.1删除多余的空白区域
一般说来,可以把那些多余的空白字符如空格,水平TAB,换行符等删除掉。不过当然了,象<pre>,<textarea>文本框和CSS的<white-space>属性中的空白是不能删除的。
1.2删除注释文字
除客户端对IE浏览器和文档类型声明条件注释之外的注释几乎都可以删除,不会对文件造成什么影响。
1.3将色值重新调整至最简短形式
在颜色上,尽量不要只使用十六进制值或只使用颜色名称,哪个短就用哪个。比如对于红颜色,用它的属性值“#ff0000”就没有“red”来得简短。而对于“浅金黄色”如果用它的颜色名“lightgoldenrodyellow”就太长了,反不如用属性值“#FAFAD2”。
1.4将文字实体重新调整至最简短形式
这一点与色值的替换类似。我们可以把一个单词名很长的文字实体用一个数字性实体来表示。
1.5删除无用的标识
将无用代码删除。
二.CSS的优化
我们可以对CSS代码进行精简来进一步减小文件的大小。不过,如今大多数网站所创建的CSS都要比普通HTML难压缩的多。对CSS的代码精简有下面这样一些安全有效的措施:
2.1删除CSS空白
CSS对空白的敏感度远远低于(X)HTML,因而可将CSS中的空白删除来有效降低CSS文件和样式表区域的大小。
2.2删除CSS注释信息
就象删除普通代码中的注释来精简代码一样,由于CSS中的注释对普通的终端用户来说并没有什么实用价值,所以应予删除。不过,如果需要考虑改进过的浏览器,则可以保留在CSS的<style>中的屏蔽注释信息。
2.3将CSS中色值调整至最简短形式
这一点也和HTML相似。对CSS字体颜色可以用单词或十六进制格式。不过,这样做在CSS中的效果会更为显著一些。这是因为CSS支持3位6进制色值,例如对白色(#ffffff)可用“#fff”来表示。
2.4对CSS设置进行重组,减少及删除
CSS中设定了字体的大小,字重,颜色等。一般CSS内容都是:
p{font-size:36pt;
font-family:Arial;
line-height:48pt;
font-weight:bold;}
我们可以将其改写成:p{font:bold36pt/48ptArial;}
如果运用得当的话,可以对样式表中的一些语法规则进行大幅削减。不过目前还没有这样的工具,所以我们只能手工删除,不过即将推出的w3compiler2.0版将会包含这一特性。
2.5重命名类和ID值
在CSS优化中,对样式表或ID值的重命名可能是最危险的一个步骤。对样式表的重命名可以遵循这样的原则:例如对于:.superSpecial{color:red;font-size:36pt;}则可将其更名为sS。而对ID值一样可以遵循这样的原则,例如对于:#firstParagraph{background-color:yellow;}则可将原来的"#firstParagraph"更名为"#fp"。自然,这样做可能会牵涉到“标识-样式-脚本”的问题:如果一个“tag”有一个ID值,而这个值又可能不但用于样式表,还可能用于脚本参考,甚至可能是一个链接目标地址。在这种情况下一旦修改了这个值,那么必须确保对所有文件中相关的脚本和链接参考都进行了相应的修改。
请注意:最好不要更改名称属性,尤其是表单区域中的名称属性。因为这些数值也会被服务器端程序操作。
三.javascript优化
1.减少下载时间优化
类似css,也是要在运行环境下删除所有空白及注释,甚至删除换行和制表符,更甚者为了减少代码字符数,可以将参数和变量全部替换为单字符的,以尽量减少客户端下载时间。当然从代码逻辑的角度进行优化以减少代码行数,也不失为有效方法。这里需要补充说明是单个TCP-IP包中能放入的字节数是1160,最好将每个javascript文件,css文件等都保持在1160字节以下以获取最优下载时间。
2.执行时间优化
javascript是一种解释型的语言,它比编译型的C程序慢5000倍;比解释型的java慢100倍;比解释型的Perl慢10倍。
不过我们仍然可以做一些事来优化javascript代码的
2-1.关注范围
javascript的范围可以认为是某个变量存在的空间,浏览器的默认范围是window。而在函数中定义的变量只存在于函数范围内,函数执行完毕时就销毁,可以认为javascript的范围是一个树状层次。引用变量时,javascript解释程序先在最近的范围内查找其是否存在。如果没有,就往上一层次查找,直到window范围,如果最终也没有找到变量,就会出现错误。这里提供两个简单的方法帮助解释程序快速定位变量:
(1)使用局部变量
在函数中,总是用var语句来声明变量,一旦使用var就会在当前范围内创建一个局部变量;而如果不使用var进行声明,则变量就创建在window范围内,这样每次使用这个变量,解释程序都会搜索整个范围树。
(2)避免with语句
with相当于另一个范围,使用时,它强制解释程序不仅在范围树内查找局部变量,还强制检测每个变量及其制定的对象,看其是否为特性。
2-2.优良的算法及数据结构
2-3.避免一些javascript陷阱
(1)如果一次需要进行多个字符串的连接,最好使用StringBuffer对象,用join()等方法,而不要使用“+”号连接。
(2)优先使用javascript内置方法,因为内置方法是由C++/C之类的语言编译的,运行起来要比必须实时编译的javascript快得多,所以最好使用内置操作而不是自己定义的函数。
(3)存储常用值
比如:oDiv1.style.left=document.body.clientWidth;
oDiv2.style.left=document.body.clientWidth;
可改为:
variClientWidth=document.body.clientWidth;
oDiv1.style.left=iClientWidth;
oDiv2.style.left=iClientWidth;
后者的效率提高很多
(4)最小化语句数量的一些方法
用一个var语句一次定义多个变量
如:variFive=5,sColor="blue",aValues=[1,2,3],oDate=newDate();
比用四个var定义四行代码好
varsName=sValues[i];
i++;
可改为:varsName=sValues[i++];
使用数组和对象的字面量
比如:
varoPerson=newObject;
oPerson.name="jack0511";
oPerson.age="25";
可改为:
varoPerson={name:"jack0511",age:"25"};
(5)节约使用DOM
DOM处理,是javascript最耗时的操作之一。不管是添加、删除还是其它对页面DOM结构的修改,都会导致明显的时间损耗。因为DOM操作需要更改页面对用户的表现,必须对整个页面进行重新计算以保证进行了正确的渲染。
处理DOM文档时,如果要进行多次改动,最好在直接应用到文档上之前,用文档碎片来保存改动。
如:varoUL=document.getElementById("ulItems");
varoFragment=document.createDocumentFragment();
for(vari=0;i<10;i++){
varoLI=document.createElement("li");
oLI.appendChild(document.createTextNode("Item"+i));
oFragment.appendChild(oLI);
}
oUL.appendChild(oFragment);
jsp/servlet程序级优化
本文讲述了调整JSP和servlet的一些非常实用的方法,它可使你的servlet和JSP页面响应更快,扩展性更强。而且在用户数增加的情况下,系统负载会呈现出平滑上长的趋势。在本文中,我将通过一些实际例子和配置方法使得你的应用程序的性能有出人意料的提升。其中,某些调优技术是在你的编程工作中实现的。而另一些技术是与应用服务器的配置相关的。
方法一:在servlet的init()方法中缓存数据
当应用服务器初始化servlet实例之后,为客户端请求提供服务之前,它会调用这个servlet的init()方法。在一个servlet的生命周期中,init()方法只会被调用一次。通过在init()方法中缓存一些静态的数据或完成一些只需要执行一次的、耗时的操作,就可大大地提高系统性能。
例如,通过在init()方法中建立一个JDBC连接池是一个最佳例子,假设我们是用jdbc2.0的DataSource接口来取得数据库连接,在通常的情况下,我们需要通过JNDI来取得具体的数据源。我们可以想象在一个具体的应用中,如果每次SQL请求都要执行一次JNDI查询的话,那系统性能将会急剧下降。解决方法是如下代码,它通过缓存DataSource,使得下一次SQL调用时仍然可以继续利用它:
publicclassControllerServletextendsHttpServlet
{
privatejavax.sql.DataSourcetestDS=null;
publicvoidinit(ServletConfigconfig)throwsServletException
{
super.init(config);
Contextctx=null;
try
{
ctx=newInitialContext();
testDS=(javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
catch(NamingExceptionne)
{
ne.printStackTrace();
}
catch(Exceptione)
{
e.printStackTrace();
}
}
publicjavax.sql.DataSourcegetTestDS()
{
returntestDS;
}
...
...
}
方法2:禁止servlet和JSP自动重载(auto-reloading)
Servlet/JSP提供了一个实用的技术,即自动重载技术,它为开发人员提供了一个好的开发环境,当你改变servlet和JSP页面后而不必重启应用服务器。然而,这种技术在产品运行阶段对系统的资源是一个极大的损耗,因为它会给JSP引擎的类装载器(classloader)带来极大的负担。因此关闭自动重载功能对系统性能的提升是一个极大的帮助。
方法3:不要滥用HttpSession
在很多应用中,我们的程序需要保持客户端的状态,以便页面之间可以相互联系。但不幸的是由于HTTP具有天生无状态性,从而无法保存客户端的状态。因此一般的应用服务器都提供了session来保存客户的状态。在JSP应用服务器中,是通过HttpSession对像来实现session的功能的,但在方便的同时,它也给系统带来了不小的负担。因为每当你获得或更新session时,系统者要对它进行费时的序列化操作。你可以通过对HttpSession的以下几种处理方式来提升系统的性能:
?如果没有必要,就应该关闭JSP页面中对HttpSession的缺省设置:如果你没有明确指定的话,每个JSP页面都会缺省地创建一个HttpSession。如果你的JSP中不需要使用session的话,那可以通过如下的JSP页面指示符来禁止它:
<%@pagesession="false"%>
?不要在HttpSession中存放大的数据对像:如果你在HttpSession中存放大的数据对像的话,每当对它进行读写时,应用服务器都将对其进行序列化,从而增加了系统的额外负担。你在HttpSession中存放的数据对像越大,那系统的性能就下降得越快。
?当你不需要HttpSession时,尽快地释放它:当你不再需要session时,你可以通过调用HttpSession.invalidate()方法来释放它。
?尽量将session的超时时间设得短一点:在JSP应用服务器中,有一个缺省的session的超时时间。当客户在这个时间之后没有进行任何操作的话,系统会将相关的session自动从内存中释放。超时时间设得越大,系统的性能就会越低,因此最好的方法就是尽量使得它的值保持在一个较低的水平。
方法4:将页面输出进行压缩
压缩是解决数据冗余的一个好的方法,特别是在网络带宽不够发达的今天。有的浏览器支持gzip(GNUzip)进行来对HTML文件进行压缩,这种方法可以戏剧性地减少HTML文件的下载时间。因此,如果你将servlet或JSP页面生成的HTML页面进行压缩的话,那用户就会觉得页面浏览速度会非常快。但不幸的是,不是所有的浏览器都支持gzip压缩,但你可以通过在你的程序中检查客户的浏览器是否支持它。下面就是关于这种方法实现的一个代码片段:
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsIOException,ServletException
{
OutputStreamout=null
Stringencoding=request.getHeader("Accept-Encoding");
if(encoding!=null&&encoding.indexOf("gzip")!=-1)
{
response.setHeader("Content-Encoding","gzip");
out=newGZIPOutputStream(response.getOutputStream());
}
elseif(encoding!=null&&encoding.indexOf("compress")!=-1)
{
response.setHeader("Content-Encoding","compress");
out=newZIPOutputStream(response.getOutputStream());
}
else
{
out=response.getOutputStream();
}
...
...
}
方法5:使用线程池
应用服务器缺省地为每个不同的客户端请求创建一个线程进行处理,并为它们分派service()方法,当service()方法调用完成后,与之相应的线程也随之撤消。由于创建和撤消线程会耗费一定的系统资源,这种缺省模式降低了系统的性能。但所幸的是我们可以通过创建一个线程池来改变这种状况。另外,我们还要为这个线程池设置一个最小线程数和一个最大线程数。在应用服务器启动时,它会创建数量等于最小线程数的一个线程池,当客户有请求时,相应地从池从取出一个线程来进行处理,当处理完成后,再将线程重新放入到池中。如果池中的线程不够地话,系统会自动地增加池中线程的数量,但总量不能超过最大线程数。通过使用线程池,当客户端请求急剧增加时,系统的负载就会呈现的平滑的上升曲线,从而提高的系统的可伸缩性。
方法6:选择正确的页面包含机制
在JSP中有两种方法可以用来包含另一个页面:1、使用include指示符(<%@includefile=”test.jsp”%>)。2、使用jsp指示符(<jsp:includeepage=”test.jsp”flush=”true”/>)。在实际中如果只需静态包含,则使用第一种方法的话,可以使得系统性能更高。
方法7:正确地确定javabean的生命周期
JSP的一个强大的地方就是对javabean的支持。通过在JSP页面中使用<jsp:useBean>标签,可以将javabean直接插入到一个JSP页面中。它的使用方法如下:
<jsp:useBeanid="name"scope="page|request|session|application"class=
"package.className"type="typeName">
</jsp:useBean>
其中scope属性指出了这个bean的生命周期。缺省的生命周期为page。如果你没有正确地选择bean的生命周期的话,它将影响系统的性能。
举例来说,如果你只想在一次请求中使用某个bean,但你却将这个bean的生命周期设置成了session,那当这次请求结束后,这个bean将仍然保留在内存中,除非session超时或用户关闭浏览器。这样会耗费一定的内存,并无谓的增加了JVM垃圾收集器的工作量。因此为bean设置正确的生命周期,并在bean的使命结束后尽快地清理它们,会使用系统性能有一个提高
其它一些有用的方法
?在字符串连接操作中尽量不使用“+”操作符:在java编程中,我们常常使用“+”操作符来将几个字符串连接起来,但你或许从来没有想到过它居然会对系统性能造成影响吧?由于字符串是常量,因此JVM会产生一些临时的对象。你使用的“+”越多,生成的临时对象就越多,这样也会给系统性能带来一些影响。解决的方法是用StringBuffer对像来代替“+”操作符。
?避免使用System.out.println()方法:由于System.out.println()是一种同步调用,即在调用它时,磁盘I/O操作必须等待它的完成,因此我们要尽量避免对它的调用。但我们在调试程序时它又是一个必不可少的方便工具,为了解决这个矛盾,我建议你最好使用Log4j工具(http://Jakarta.apache.org),它既可以方便调试,而不会产生System.out.println()这样的方法。
?ServletOutputStream与PrintWriter的权衡:使用PrintWriter可能会带来一些小的开销,因为它将所有的原始输出都转换为字符流来输出,因此如果使用它来作为页面输出的话,系统要负担一个转换过程。而使用ServletOutputStream作为页面输出的话就不存在一个问题,但它是以二进制进行输出的。因此在实际应用中要权衡两者的利弊。
总结
本文的目的是通过对servlet和JSP的一些调优技术来极大地提高你的应用程序的性能,并因此提升整个J2EE应用的性能。通过这些调优技术,你可以发现其实并不是某种技术平台(比如J2EE和.NET之争)决定了你的应用程序的性能,重要是你要对这种平台有一个较为深入的了解,这样你才能从根本上对自己的应用程序做一个优化!
background-color: blue;background-color: yellow;<input type="button" value="变蓝" @click="changeColorT