標籤:
總結:Java沒有足夠的堆大小可能會導致效能非常大的影響,這無疑將給予必要的程式,並不能帶來麻煩。本文總結了影響Java居前五位的能力不足,並整齊地疊最佳化?
筆者Pierre有一個10進階系統架構師有多年經驗,他的主要專業領域是Java EE、中介軟體和JVM技術。依據他多年的工作實踐經驗,他發現很多效能問題都是由Java堆容量不足和調優引起的。
以下他將和大家分享很有用的5個Java堆最佳化技巧。
1.JVM:對難以理解的東西產生恐懼感
千萬不要以為,通過配置,調優。就能夠排除那些你所不明確的問題。
有些人覺得Java程式猿不需要知道內部JVM記憶體管理。
毫無疑問,這樣的觀點明顯是錯誤的,假設想拓寬知識面和提升排除故障能力。你就必需要瞭解和學習一下JVM記憶體管理。
對於Java或者是Java EE新手來說,Java Heap調優和故障排除是一項很有挑戰的工作。
以下會提供一些典型的案例情境:
client環境面臨著有規律的OutOfMemoryError錯誤而且對業務造成了非常大的影響。
你的Team Dev要在如此大的壓力下去解決問題。一般會怎麼做?
- 用Google搜尋引擎找到類似的問題而且你會相信(或如果)你也面臨相同的問題。
- 你會抓住JVM-Xms和存在OutOfMemoryError異常這幾個keyword的範例,然後希望通過這種案例來高速解決client問題。
- 最後你會在你環境中使用相同的調優方法。
兩天后,問題仍然發生(甚至更糟或者略微好點)……
究竟是哪裡錯了呢?
首先。沒有摸清問題根源所在?對開發環境沒有正確地進行深層面(規格、負載情況等)理解。網路搜尋是一個很優秀的學習方法和知識分享工具。可是你必須結合自己的實際項目。從根本上進行分析解決。
可能缺乏主要的JVM和JVM記憶體管理技能,阻止你把全部的點給串連起來。
今天講的第一條技巧是協助你理解主要的JVM原則及其與眾不同的記憶體空間。
這些知識都是相當重要的。它能夠協助你做出有效調優策略、更加正確合理的預測將來會產生的影響、提前知道未來須要做哪些調優工作。
以下來看一下JVM參考指南:
JVM記憶體分為3個記憶體空間
- Java Heap:適用於全部的JVM廠商,通經常使用來拆分YoungGen(幼苗)和OldGen(終身享用)空間。
- PermGen(永久代):適用於Sun HotSpot VM((PermGen空間在Java7或者Java8更新中將會被刪除)
- Native Heap(C-Heap):適用於全部的JVM廠商。
建議把以下的文章都能看一遍,最好把Sun的Java記憶體管理白皮書和OpenJDKS實現下載下來並細緻閱讀。
- Sun HotSpot VM
- IBM VM
- Oracle JRockit VM
- Sun(Oracle)–Java memory management white paper
- OpenJDK–Open-source Java implementation
正如你所示,JVM記憶體管理比使用Xmx設定最大值更為複雜。
你須要查看每一個角度,包含本地和PermGen需求以及從主機上查看實體記憶體可用性(CPU core)。
在較大的Java Heap和較小的本地Heap比賽中。32位虛擬機器可能會變得相當棘手。
試圖在一個32位VM如2.5GB+上設定一個大型堆。依據應用程式佔用和線程數量等因素會添加OutOfMemoryError這個異常拋出。64位JVM能夠解決問題,但實體資源可用性和記憶體回收成本仍然是有限制的(成本主要集中在GC大小收集上)。
最大並不表示是最好的,所以請不要如果在一個16GB的64位虛擬機器上能夠執行20個Java EE應用程式。
2.資料和應用程式為王:回想靜態佔用需求
應用程式以及相關資料將決定Java堆空間佔用需求。
通過靜態記憶體,可“預測”以下的記憶體需求:
在JVM進程上部署的應用程式越多,對本地記憶體和PermGen空間的要求就越高。資料緩衝並非序列化為一個磁碟或資料庫,它將從OldGen空間裡面須要額外的記憶體。
設法對靜態記憶體佔用進行合理的評估,在真正進行資料測試之前,設定一些JVM能力起點是很實用的。
對於32位JVM,通常不推薦一個Java堆大小超過2 GB(-Xms2048m,-Xmx2048m),對於Java EE應用程式和線程來說這樣將須要足夠的記憶體和本機堆PermGen。
這個評估是非常重要由於太多的應用程式部署在一個32位JVM進程上非常easy導致本機堆耗盡;尤其是在多重線程環境。
對於64位JVM。 一個3GB或者4GB的Java堆/JVM進程是推薦的起點。
3.業務流量設定規則:審查動態記憶體佔用需求
業務流量一般會決定動態記憶體佔用。通過觀察各種監控工具能夠發現並發使用者與請求產生的JVM GC“心跳”。這是因為頻繁的建立和記憶體回收短期或者長期對象。
一個典型的32位JVM,Java堆大小設定在2 GB(使用分代&並發收集器)通常為500 MB YoungGen分配空間和1.5 GB的OldGen空間。
最大限度地降低重大GC收集的頻率是獲得最佳效能的關鍵因素,所以在高峰的時候理解和評估須要多少記憶體是很重要的。
再次聲明,應用程式類型和資料將決定記憶體需求。購物車的應用程式類型(長期居住的對象)涉及大型和非序列化會話資料,這個通常須要大型Java堆和非常多OldGen空間。
無狀態和XML處理(非常多短命的對象)繁重的應用程式須要適當YoungGen空間。以盡量降低頻率主要集合。
比如:
你有5個ear應用程式(2000多個Java類)要部署(包括中介軟體代碼)
- 本地堆需求預計為1GB(必須足夠大以處理線程建立等等。)PermGen空間大約是512 MB。
- 內部靜態緩衝大約500MB
- 在高峰時間。總預測流量是5000個並發使用者
- 每一個使用者的會話資料大約500K
- 在高峰期間,總流量會話要求是2.5GB。
正如你所示一樣,在如此情況下,32位JVM進程就無法滿足。
一個典型的解決方式是進行流量拆分,在幾個JVM進程或物理主機(如果有足夠的硬體和CPU core可用)上。
大多數時候,業務流量將推動記憶體佔用。
除非你須要大量的資料緩衝來實現適當的效能,典型的門戶應用網站(媒體)繁重的應用程式需求。資料緩衝太多的時候應該用一個黃色的標誌標註一下。最好早點去又一次審視一下一些設計項目。
4.量體裁衣
這一條,你應該做到:
- 理解主要的JVM原則和記憶體空間。
- 對全部應用程式有深入的瞭解及其他們的特點(大小、類型、動態流量、無狀態對象VS有狀態物件、內部記憶體緩衝等)。
- 對預測業務流量(並發使用者)給每個應用程式能提出非常好的觀點—假設你須要一個64位的虛擬記憶體,那麼將設定哪個作為開始。
假設須要多個JVM(中介軟體)過程。
等一下。這樣做並不足夠。儘管上面的資訊是至關重要的,而且關於Java堆的設定進行了“最佳推測”。相應用程式的行為進行類比而且進行適當的分析、負載和效能測試來驗證Java堆記憶體要求。
推薦Jprofiler工具給大家,學習怎樣使用一個分析器的最好方法是正確理解應用程式的記憶體佔用。還有一個方法是使用Eclipse MAT工具依據現有的環境進行堆轉儲分析。
堆轉儲很強大,它能夠同意你查看和理解Java堆的整個記憶體佔用,包括類載入器相關資料和在記憶體佔用分析中必需要做的,特別是記憶體流失。
Java分析器和堆轉儲分析工具同意你理解和驗證應用程式記憶體足跡。包括記憶體流失的檢測和解決方式。
負載測試和效能測試是不可缺少的,通過類比並發使用者來驗證早期評估是否正確,它也會把應用程式瓶頸暴露出來而且同意你進行微調。推薦一個很easy上手的工具:Apache Jmeter。
最後將看一下這種情況。應用程式在Java EE環境很正常,直到有一天全然正常的裝置啟動失敗,比如硬體問題。
突然的環境執行能力下降和總體環境下降,究竟發生了什嗎?
引起“多米諾效應”的原因有非常多,但缺少JVM調優和處理容錯移轉的能力(短期額外負荷)是非經常見的。
假設JVM進程執行在80% + OldGen空間容量和頻繁的垃圾收集,你怎樣預期容錯移轉情境?
前面類比的負載和效能測試應該類比這種情境,調整你的調優設定使您的Java堆有足夠的緩衝來處理額外的負載(額外的對象)在短期內。
這主要適用於動態記憶體佔用,因為容錯移轉意味著將重新導向一些固定的並發使用者給可利用的JVM進程(中介軟體執行個體)。
5.分而治之
這一條的前提是你已經完畢了幾十個負載測試。JVM已經不存在泄露,你的應用程式記憶體不能再進行不論什麼降低。你已經嘗試了幾個調優策略。比如使用一個64位的Java堆空間在10GB以上。多個GC策略,雖然這樣,仍然沒有找到合適的能夠接受的效能水平?
與當前的JVM規範相比。適當的垂直和水平伸縮。包含在每一個物理主機和跨多個主機上建立JVM進程來滿足整個輸送量和容量。假設在幾個邏輯倉、自身的JVM進程、線程和調優值裡打破應用程式列表那麼IT環境的容錯能力將更強大。
“分而治之”策略包含拆分應用程式流程量到多個JVM進程,以下提供一些拆分技巧:
- 降低每一個JVM進程的Java堆大小(靜態和動態佔用)
- 降低JVM調優複雜度。
- 降低GC流失和暫停每一個JVM進程
- 添加冗餘和故障切換功能
- 排列最新的Cloud和IT虛擬化戰略
當你發現已經花費了大量的時間在64位JVM進程調優上,是時候該好好審視一下你的中介軟體和JVM部署策略而且利用垂直和水平縮放。這條策略的許多認識需要支援其他硬體,但是從長遠來看,。這是非常有效,故意的。(章盧南/編)
著作權聲明:本文部落格原創文章。部落格,未經同意,不得轉載。
最佳化Java堆大小5溫馨提示