關於java性能的小筆記
一、大規模高並發訪問的性能分析:
1.應用服務器中JVM的優化:
在安裝JDK後,有兩個JVM虛擬機,分別是server jvm和 client jvm。其中server jvm比client jvm進行了更多的優化,所以在開發和測試Web應用係統時,應用指定服務器的jvm虛擬機為server jvm。
啟動client jvm 和server jvm的方式:
Java –client yourclass
Java –server yourclass
其中client jvm是默認的啟動方式。在tomcat服務器中,通常會有如下兩種設置jvm虛擬機的方式:
● %java_home%/jre/bin/client/jvm.dll
● %java_home%/jre/bin/server/jvm.dll
Jvm動態庫有client和server兩個版本,分別針對桌麵應用和服務器應用做了相應優化,其中client版本加載速度較快,server版本加載速度較慢但運行起來較快。一般在tomcat服務器中,應使用server版本。
2. JVM虛擬機中對字節碼優化的策略:
Server jvm和client jvm對字節碼優化的策略不同:
●Client主要優化對用戶交互的相應速度。
●Server主要優化後台運行的代碼。
使用server模式可以提高性能,啟動比client模式慢,長期運行則比client模式快。當該參數不指定時,虛擬機啟動檢測主機是否為服務器,如果是,則以server模式啟動,否則以client模式啟動。J2SE 5.0檢測的根據是至少2個CPU和最低2GB內存。
3. 堆大小設置:
JVM中最大堆大小有三方麵限製:相關操作係統的數據模型(32bit還是64bit)限製;係統的可用物理內存限製。在32位係統下,一般限製在1.5-2G,在64位係統下,操作係統對內存無限製。
常用的典型設置如下:
●Java –Xmx3550m –Xms3550m –Xmn2g –Xss128k
●-Xmx3550m: 設置JVM最大可用內存為3550。
-Xms3550m:設置JVM初始化內存為3550M。此值可以設置於-Xmx相同,以避免每次垃圾回收完成後JVM重新分配內存。
-Xmn2g:設置年輕代大小為2G。整個堆大小=年輕代大小+年老代大小+持久代大小。持久代大小一般固定大小為64M,所以增大年輕代後,將會減小年老代大小。此值對係統性能影響較大,Sun 官方推薦配置為整個堆的3/8。基於對對象生命周期分析後得出的垃圾回收算法,把對象分為年輕代,年老代,持久代,對不同的生命周期的對象使用不同的算法(上述方式中的一個)進行回收。現在的垃圾回收器(從J2SE 1.2開始)都是使用此算法的。
-Xss128k:設置每個線程的堆棧大小。從JDK5.0每個堆線程大小為1M,以前每個線程堆大小為256K。可根據具體應用調整線程所需內存大小。在相同物理內存下,減小這個值能生成更多的線程。但是操作係統對一個進程內的線程數還是有限製的,不能無限生成,通常值在3000~5000左右。
4.回收器選擇:
在JVM中給三種回收器的選擇:串行收集器、並行收集器、並發收集器,但是串行收集器隻適用於小數據量的情況,所以這裏的選擇主要針對並行收集器和並發收集器。默認情況下,在JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在啟動時加入相應參數,從JDK5.0以後,JVM會根據當前係統配置進行判斷。
並行收集器主要以達到一定的吞吐量為目標,適用於科學技術和後台處理等,典型配置如下:
java-Xmx2800m-Xms800m-Xmn2g-Xss128k-XX:+UserParallelGC-XX:ParallelGCThreads=20-XX:+UserParallelOldGC
●-XX:+UserParallelGC:選擇垃圾收集器為並行收集器。此配置僅對年輕代有效。即上述配置下,年輕代使用並發收集,而年老代仍舊使用串行收集。
●-XX:ParallelGCThreads=20:配置並行收集器的線程數,即同時多少個線程一起進行垃圾回收。此值最好配置與處理器數目相等。
●-XX:+UserParallelOldGC:配置年老代垃圾收集方式為並行收集,JDK6.0支持對年老代並行收集。
並發收集器主要是保證係統的響應時間,減少垃圾收集時的停頓時間。適用於應用服務器、電信領域等。典型配置如下:
Java-Xmx3550m-Xms3550-Xmn2g-Xss128k-XX:ParallelGCThreads=20-XX:+UserConcMarkSweepGC-XX:+UserParNewGC
●-XX:+UseConcMarkSweepGC:設置年老代為並發收集。
●-XX:+UseParNewGC:設置年輕代為並行收集。可與CMS收集同時使用。從JDK5.0開始,JVM會根據係統配置自行設置,所以無需再設置此值。
5.年輕代大小選擇:
響應時間優先的應用:年輕代盡可能設大,直到接近係統的最低響應時間限製(根據實際情況選擇)。在此種情況下,年輕代收集發生的頻率也是最小的。同時減少到達年老代對象。
吞吐量優先的應用:年期代盡可能的設置大,可能達到Gbit的程度。因為對響應時間沒有要求,垃圾收集可以並行進行,一般適合8CPU以上的應用。
6.年老代大小選擇:
響應時間優先的應用:年老代使用並發收集器,所以其大小需要小心設置,一般要考慮並發會話率和會話持續時間等一些參數。如果堆設置小了,可能會造成內存碎片、高回收頻率以及應用暫停而使用傳統的標記清除方式:如果堆大了,則需要較長的收集時間。最優化的方案,一般需要參考以下數據獲得:
● 並發垃圾收集信息。
● 持久代並發收集次數
● 傳統GC信息
● 花在年輕代和年老代回收上的時間比例
● 減少年輕代和年老代花費的時間,一般會提高應用的效率
吞吐量優先的應用:一般吞吐量優先的應用都有一個很大的年輕代和一個較小的年老代。原因是:這樣可以盡可能回收掉大部分短期對象,減少中期的對象。
7.較小堆引起的碎片分析:
因為年老代的並發收集器使用標記、清除算法,所以不會對堆進行壓縮。當收集器回收時,它會把相鄰的空間進行合並,這樣可以分配給較大的對象。但是當堆空間較小時,運行一段時間以後,就會出現“碎片”,如果並發收集找不到足夠的空間,那麼並發收集器將會停止,然後使用傳統的標記、清除方式進行回收。如果出現“碎片”,可能需要進行如下配置:
●-XX:+UserCMSCompactAtFullCollection:使用並發收集器時,開啟對年老代的壓縮。
●-XX:CMSFullGCsBeforeCompaction=0:上麵配置開啟的情況下,這裏設置多少次Full GC後,對年老代進行壓縮。
8.在實際編程中對內存的優化:
應用java開發的係統給人的印象是占內存,其實從理論上來講,java開發的係統並不比其他語言開發的係統更占用內存,這就需要子啊編程時注意優化內存。
●不要使用new Boolean().
●不要使用new Integer()
●用StringBuffer代替字符串相加
●過濫使用哈希表
●避免過深的類層次結構和過深的方法調用。因為這兩者都是非常占用內存的(特別是方法調用更是堆棧空間的消耗大戶)
●變量隻用在用到它的時候才定義和實例化
●盡量避免使用static變量,類內私有常量可以有final來代替
●盡早釋放無用對象的引用
●盡量少用finalize函數。它會增加GC的工作量
●盡量避免在類的默認構造器中創建和初始化大量的對象,防止在調用其構造器時造成不必要的內存資源浪費
●盡量避免強製顯示申請數組空間
●盡量做遠程方法調用類應用開發時使用瞬間值變量,除非遠程調用端需要獲取該瞬間值變量的值。
●盡量在合適的場景下使用對象池技術以提高係統性能
9.集群與負載均衡
在單一的服務器上執行某些應用程序會出現一些重大問題。當網站成功建成並開始接受大量請求時,單一服務器終究無法滿足需要處理的負荷量,所以就顯得有點力不從心了。另外一個常見的問題是會產生單點故障,如果該服務器壞掉,那麼網站就立刻無法運行了。不論是因為要有較佳的擴充性還是要有容錯能力。都希望在一台以上的服務器計算機上執行該應用程序,這就需要用到集群技術。
集群(luster)一組獨立的計算機係統構成一個鬆耦合的多處理係統,他們之間通過網絡實現進程間的通信。應用程序可以通過網絡共享內存進行消息傳送,實現分布式計算機。
集群係統主要解決下麵幾個問題:
● 高可靠性(HA):利用集群管理軟件,當主服務器故障時,備份服務器能夠自動接管主服務器的工作,並及時切換過去,以實現對用戶的不間斷服務。
● 高性能計算(HP):即充分利用集群中的每一台計算機的資源,實現複雜運算的並行處理,通常用於科學計算領域,如基因分析,化學分析。
● 負載平衡:即把負載壓力根據某種算法合理分配到集群中每一台計算機上,以減輕服務器壓力,降低對主服務器的硬件和軟件需求。
● 負載均衡(oad Balance):集群就是一組連在一起的計算機,從外部看它是一個係統,各節點可以是不同的操作係統或不同硬件構成的計算機。如一個提供Web服務的集群,從外界來看是一個大的WEB服務器。不過集群的節點也可以單獨提供服務。在現有網絡結構之上,負載均衡提供了一種廉價有效的方法擴展服務器帶寬和增加吞吐量,加強網絡數據處理能力,提高網絡的靈活性和可用性。
目前比較常用的負載均衡技術主要如下:
1.基於DNS的負載均衡
a) 通過DNS服務中的隨機名字來實現負載均衡,在DNS服務器中,可以為多個不同的地址配置同一個名字,而最終查詢這個名字的客戶機講在解析這個名字時得到其中一個地址,因此,對於同一個名字,不同的客戶機會得到不同的地址,他們也就訪問不同地址上的WEB應用服務器,從而達到負載均衡的目的。
反向代理負載均衡最後更新:2017-04-02 06:51:45