最佳化WebSphere套用性能技巧集錦

  最佳化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="formchek.js"。

其他減少網路傳輸應當注意的地方還包括:避免過度使用隱藏域,減少超長cookie值,在radio、checkbox和select域中用代碼來替代長長的字元串,等等。不過在html最佳化方面本文不準備作全面的討論,因為websphere套用的開發者一般不會擔負設計表現層的責任,只要了解下面這個原理就足夠了: 

性能技巧之一:儘可能減少http數據傳輸的總量和頻度 

二、資料庫訪問 

朋友小a對java的了解極為有限,但他卻成功地改進了許多websphere套用的性能。他是怎么做到的呢?原來,小a是一個資料庫專家,他通過最佳化資料庫訪問有效地改進了整個套用的性能,但對於java,他只是略微了解一些有關jdbc的知識。在最佳化資料庫訪問時,小a做的第一件事情總是檢查資料庫的設計,有時他會建議重新構造資料庫的結構(必須指出的是,為了提高性能而重新構造資料庫結構有時可能使資料庫反規格化(de-normalization),從而帶來維護方面的問題)。
性能技巧之二:規格化(normalization)資料庫結構

小a做的第二件事情是執行資料庫分析,根據分析結果提出增加某個索引、減少某個索引的建議。完成這一步驟後,小a通常可以讓套用有令人滿意的性能表現,根本不必去查看套用的java代碼。 

性能技巧之三:針對常用的sql操作建立索引,刪除多餘的索引 

有時,為了進一步最佳化套用的性能,小a會檢查java(也許應該說是sql)代碼,經常找到java程式沒有合理運用preparedstatement和連線緩衝池的情形。只要把statement類的動態sql替換成preparedstatement類的靜態sql,從連線池提取sql連線(而不是直接創建連線),套用的性能將得到顯著的改善。注意db2 udb(包括其他一些資料庫)的preparedstatement是可調整和配置的。 

性能技巧之四:合理運用preparedstatement和連線池 

進一步分析套用的工作流程之後,小a有時會建議批量執行某些sql命令,這樣就只需一個對資料庫伺服器的請求就可以運行大量的sql命令。 

性能技巧之五:考慮批量執行sql命令

既然如此,小a有時還會指出,如果套用中有些sql命令可以組合成單個事務邏輯,那么應該可以用一個存儲過程來替代。db2 udb的存儲過程語言(spl,stored procedure language)非常強大,如果把資料庫操作邏輯從web套用轉移到資料庫,一般總是對性能有益。不過需要注意的是,雖然批量執行sql命令或使用存儲過程會提高性能,但就象重新構造資料庫結構一樣,有時會帶來維護方面的困難。 

性能技巧之六:考慮使用資料庫存儲過程

檢查jdbc代碼的時候,小a總是留意對象有沒有及時正確釋放。這一點其實很重要。 

性能技巧之七:及時關閉不用的statement、resultset、connection等對象(但不是在finalize方法內) 

三、java代碼 

前面我們以小a的經驗為例,探討了web套用中資料庫訪問性能的重要性。調整好資料庫之後,接下來要做的自然是深入分析套用的java代碼。從哪裡入手呢?你最好使用java分析工具來找出性能問題的焦點所在。最佳化java代碼的性能是一個艱苦的過程,因此一個重要的原則是把精力集中到那些可能引起性能問題的代碼上。換句話說,就是要尊重80/20規則:利用java分析工具的結果,調整帶來80%性能開銷的那20%代碼。 

性能技巧之八:用java分析工具清楚地界定性能問題所在 

目前市場上已經有許多優秀的java分析工具,例如ej-technologie的jprofile(),klgroup的jprobe(),以及intuitive systems的optimizeit()。不過不要忘記websphere studio application developer(wsad)本身也集成了一個優秀的分析器,有條件的話,最好多用幾種分析工具分析java代碼。 

考慮到資金問題,你不一定樂意購買昂貴的分析軟體,但你可以用java本身的命令行工具生成分析信息。例如,在jdk 1.3中,你可以用下面的命令將testorderprocessing類的cpu使用情況保存到java.hprof檔案:java -xrunhprof:cpu=times,format=a,file=java.hprof testorderprocessing。 

這種辦法的缺點是它提供的信息條理不夠清楚,比較繁雜;也許可以找到一些原始碼開放的工具輔助分析,但一般不如使用wsad本身的分析工具或商業化的分析工具方便。另外,如果你已經了解哪些代碼塊可能引起性能問題,可以通過保存系統時間的方式獲得分析信息,例如: 
long starttime = system.currenttimemillis(); 
// 執行某些操作
long endtime = system.currenttimemillis();

3.1 基本篇 

有人建議“穩定性第一,速度第二”,一般而言遵從這個建議是不會錯的,但這並不妨礙我們在編寫代碼的同時運用某些已經證實的性能技巧。例如,我們都知道string類是不可變的,連線兩個string是一項開銷很大操作。 

性能技巧之九:用stringbuffer來連線兩個字元串

也許你已經注意到,sun的許多標準java類是執行緒安全的,這些類內部的同步機制實際上很容易造成性能問題。例如,vector類就是一個執行緒安全的類,除非確實要用到同步機制,否則使用vector是不值得的,如有可能,應當儘量改用非執行緒安全的類如arraylist。 

性能技巧之十:只有在必要時才運用執行緒安全的類

許多人習慣使用system.out.println來輸出跟蹤信息,但println要占用不少資源,所以輸出跟蹤信息最好使用專用日誌記錄框架,如ibm的jras或apache的log4j。 

性能技巧之十一:用日誌記錄框架類輸出跟蹤信息,而不是使用system.out.println 

最後一個提高代碼性能的簡單技巧是清除類裡面的調試信息,減小類的體積。ibm有一個wsad外掛程式,它提供了一個叫做setdebuginfo的任務,可以從ant腳本調用。 

性能技巧之十二:從正式發行的軟體中刪除調試信息