最大化 AIX 上的 Java 性能,第 3 部分: 更多就是更好
http://www.ibm.com/developerworks/cn/aix/library/es-Javaperf/es-Javaperf3.html
最大化 AIX 上的 Java 性能,第 3 部分: 更多就是更好
這個由五個部分組成的系列提供了若干技巧和技術,這些技巧和技術通常用于優化 Java? 應用程序,以便在 AIX? 上實現最佳的性能。其中還提供了有關每個技巧的適用性討論。使用這些技巧,您應該能夠快速優化 Java 環境,以適合應用程序的需要。
查看本系列更多內容?
2008 年 1 月 03 日
- 內容
在 IBM Bluemix 云平臺上開發并部署您的下一個應用。
引言
這是由五部分組成的有關 AIX 上的 Java 性能優化的系列中的第三篇文章。強烈建議您在進一步繼續之前閱讀本系列中的第 1 部分(如果您還沒有這樣做的話)。
本文集中于涉及各種類型的內存結構(Java 堆、本機堆、堆棧)的優化,并研究用于優化系統以進行大小調整的方法。
您應該查看第一部分,以了解適用于大多數情況的一般技巧。我們還提供了對于內存瓶頸檢測和研究非常有用的工具的快速參考。下一部分將描述各種類型的應用程序以及如何優化它們。此討論將利用您的應用程序知識來決定哪些技巧最適合您。第三部分將描述各種技巧。本文在結束時將討論一下本系列中的下一篇文章。
回頁首
內存瓶頸
本文討論如何使您的應用程序擴展到更多數量的線程或具有更大的堆,或者同時實現這兩個目的。您可能還希望通過迫使應用程序以受約束的方式使用資源,從而使其更加“文明”。在系統由多個應用程序共享的環境中,這是特別重要的。
當 AIX Java 應用程序嘗試擴展時,存在若干可能會產生影響的資源瓶頸。Java 堆只是其中之一,并且在大多數情況下,您只需切換到更大的堆大小即可向上擴展。但是還存在另外三個內存方面,它們對于確定 Java 應用程序的內存占用空間和可伸縮性具有重要的影響。
除 Java 堆以外的第一個重要內存方面是本機堆(native heap),文章“Getting more memory in AIX for your Java applications”?描述了如何監視本機堆和調整其大小。Java 堆由垃圾收集器(Garbage Collector)管理,但是垃圾收集器不會對本機堆執行任何操作。因此,如果您看到本機堆穩定地增加,可能是由于不匹配的 JNI 分配(舉例而言)所導致的。
第二個方面是用?-Xss?指定的本機堆棧(native stack)。這是針對每個線程分配的,并且不基于具體的使用情況,因此如果計劃運行一百個線程,則要在指定?-Xss2m?前慎重考慮;它將消耗 200 MB 的本機內存,每個線程消耗 2 MB。在運行更多數量的線程時,這尤其成為一個限制因素,建議的解決辦法是使用較小的值而不是使用缺省值。與 JVM 配套的 SDK 指南中提供了有關此主題的更多信息。
最后,第三個方面是通過?-Xoss?控制的 Java 堆棧(Java stack)。使用?-Xoss?指定的值是上限,因此指定一個較大的值的效果不如使用?-Xss那么顯著。請注意,由于 JIT 編譯,您需要調整?-Xss?以滿足大多數需要,并且?-Xoss?通常可以保留不變。例如,需要調整?-Xoss?的一個重要場合是在用完了 JNI 引用的時候。
我們不會集中于上述任何內存方面,因為其調整通常是在調試中出現的,而不是在性能優化中出現的。但是如果您陷入了資源不足的情況,現在可以檢查這額外的三個方面。當您將系統利用到極限時,尤其必須了解這些方面。
談到極限,您應該確保?ulimit?設置不會在大小調整期間成為瓶頸。在理想的情況下,我們建議將某些?ulimit?值設置為無限大,但是需要將此行為與某個進程消耗完所有本地資源的風險進行評估。對于性能優化工作,您可以首先將?ulimit?值設置為無限大,一旦達到所需的目標,您應該將這些設置設定為有限值。
您可以使用?ulimit -a?命令檢查當前的?ulimit?設置,并且應該作為將啟動 Java 的用戶帳戶至少運行以下三個命令:
ulimit -m unlimitedulimit -d unlimitedulimit -f unlimited在某些情況下,您可能不允許執行上述操作,因為運行 Java 的用戶帳戶可能沒有分配足夠的硬限制:有關必需的?ulimit?設置,請參閱位于IBM developer kits for AIX, Java technology edition?的 JVM 配套 SDK 指南。
請注意,與 GC 相關的問題通常會作為 CPU 資源緊張的問題出現,因此如果遇到與 GC 相關的問題,您還應該閱讀本系列的第 2 部分。此外,如果 RMI 觸發了 GC,第 4 部分將對此進行討論。
本部分的其余內容將簡單介紹一些常用的工具和如何檢測特定于 Java 的問題。有關更多詳細信息,請參見?AIX 5L Performance Tools Handbook?和?Understanding IBM eServer pSeries Performance and Sizing。
vmstat
vmstat?已在本系列的第 2 部分進行了介紹。要從?vmstat?輸出中最需要了解的信息是是否發生了分頁,以及分頁是否是由于堆大小大于可用的物理內存而導致的。在大多數情況下,由于更大的堆而獲得的任何可伸縮性好處,都抵不過由于堆分頁而導致的嚴重性能降低,因此應該避免使用較大的堆。
svmon
svmon?是監視 Java 進程(尤其是本機堆)時最有用的工具。文章“When segments collide”(http://www.ibm.com/developerworks/eserver/library/es-segcollide.html)提供了如何使用?svmon -P <pid> -m?來監視 AIX 上的 Java 進程本機堆的示例。但是還存在另一種形式?svmon -P <pid> -m -r,此命令對于確定本機堆碎片非常有效。?-r?開關打印正在使用的地址范圍,因此它提供了每個段的當前使用情況的更準確視圖。例如,請考慮下面經過部分編輯的輸出:
Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd LPage10556 java 681613 2316 2461 501080 N Y NVsid Esid Type Description LPage Inuse Pin Pgsp Virtual22ac4 9 mmap mapped to sid b1475 - 0 0 - - 21047 8 mmap mapped to sid 30fe5 - 0 0 - - 126a2 a mmap mapped to sid 91072 - 0 0 - - 7908c 7 mmap mapped to sid 6bced - 0 0 - - b2ad6 b mmap mapped to sid b1035 - 0 0 - - b1475 - work - 65536 0 282 65536 30fe5 - work - 65536 0 285 65536 91072 - work - 65536 0 54 65536 6bced - work - 65536 0 261 65536 b1035 - work - 45054 0 0 45054 Addr Range: 0..45055e0f9f 5 work shmat/mmap - 48284 0 3 48284 19100 3 work shmat/mmap - 46997 0 463 47210 c965a 4 work shmat/mmap - 46835 0 281 46953 7910c 6 work shmat/mmap - 37070 0 0 37070 Addr Range: 0..50453e801d d work shared library text - 9172 0 0 9220 Addr Range: 0..30861a0fb7 f work shared library data - 105 0 1 106 Addr Range: 0..252121127 2 work process private - 50 2 1 51 Addr Range: 65300..65535a8535 1 pers code,/dev/q109waslv:81938 - 11 0 - - Addr Range: 0..11如果閱讀過文章“Getting more memory in AIX for your Java applications”,您應該能夠判斷出上述配置是使用 LDR_CNTRL=MAXDATA=0x40000000。“Inuse”列中顯示 4K 頁的值,因此一個段(大小為 256 MB)在此列中的最大值將為 65536。正如上述輸出所示,這個特定的應用程序在使用大量的本機堆;沒有為段 3-5 打印范圍的原因在于,盡管“Inuse”計數不是 65536,但是該段已經完全分配了。此外,如果沒有使用?-r,可以認為既然段 6 的“Inuse”值為 37070,則該段只有 56% 的使用率。但是可以判斷出,段 6 正在使用的實際地址范圍是 0 到 50453,或換句話說該段差不多達到 77% 的使用率。這會對應用程序的大小調整具有重要的影響。
要注意的另一個有趣部分在于,通過?svmon?無法看到 Java 堆碎片。段 7 至 A 看起來已完全利用(對應 SID 的“Inuse”值為 65536),而段 B 正在使用前 45056 個頁面。這只是告訴了您該堆的大小約為 1100 MB,但是還存在找到此信息的更容易方法(即查看 Java 的命令行參數!)。
特定于 Java 的技巧
Fine-tuning Java Garbage Collection Performance?介紹了 Java 堆的優化。在 1.4 以前的 Java 版本上,您可能需要調整某些環境設置才能使用超出 1 GB 的堆,“Getting more memory in AIX for your Java applications”對此進行了解釋。
如果您了解 verbosegc 輸出的各項意義,以及如何使用?svmon,對于 AIX 上的任何 Java 應用程序的大多數性能監視工作應該足夠了。
存在若干有關 GC 優化的文章可以使用,因此基于您希望了解此主題的深度,您可以使用大量的信息。Diagnostics 頁還指向一個總結 IBM Java 的 GC 是如何工作的文檔,對于開發人員來說這應該特別有用。下面幾個部分將堅持使用基于特征的優化方式,但是如果您希望更進一步研究任何特定的技巧,應該參考“IBM Garbage Collection and Memory Allocation techniques”一文,您可以從 http://www.ibm.com/developerworks/java/jdk/diagnosis/ 訪問它。
回頁首
基于特征的優化技巧
下面我們將看一下典型應用程序的不同特征。您應該定位到與您的應用程序類似的行為(無論是設計上的還是觀察到的),并應用對應的技巧。除非明確指明,否則術語“堆”是指 Java 堆。
堆使用情況
對于大多數應用程序,使用固定與可變堆的決定是很容易做出的。任何具有或多或少的有限堆要求的應用程序都可以使用?技巧 MEM001,而任何會定期猛增堆使用量的應用程序使用技巧 MEM002?效果會更好。但是,如果應用程序逐漸地增長,或者如果您在考慮由于可變堆大小而導致的性能影響,則技巧 MEM001 也許仍然是可行的。位于?IBM developer kits - diagnosis documentation?的診斷指南包括一個有關如何調整 Java 堆大小的不錯的內容。正如“Fine-tuning Java Garbage Collection Performance”所提到的,要遵循的規則是:分配應用程序需要的堆大小,但是決不多分配。但是在決定使用技巧 MEM001?之前,請參閱有關“堆回收”的部分。
堆增長速度
如果應用程序堆需要迅速增長,則技巧 MEM003?將會非常有用。能從快速內存增長中獲益的應用程序類型是在工作日的特定時間具有內存需求高峰的應用程序。如果優化得當,堆擴展次數將會減少,因為每次擴展會將堆增長更大的量。
另一方面,如果希望控制堆增長速度,請參見技巧 MEM004。當您看到堆擴展相當大并且希望控制擴展增量時,這是非常有用的。此類情況非常罕見,因為 Java 通常會基于定義良好的規則來擴展堆,除非您首先使用技巧 MEM003,否則堆不會快速增長。不過在需要時使用技巧 MEM004?還是有用的。
如果應用程序堆只應該增長而決不會收縮,可以使用?技巧 MEM005?來強制實現此目的。GC 周期不斷監視堆使用情況,并在看到分配的堆大于當前需求時收縮堆。畢竟,這就是使用可變大小的堆的本意。但是有時,您可能注意到在堆收縮后,由于堆需求的增長而緊跟著進行堆擴展。在此情況下,您可以要求 JVM 不要收縮堆。
堆回收
如果應用程序生成大量的臨時對象,如果可以設置足夠小的堆,則技巧 MEM001?將會很有幫助。其基本思路在于,如果堆增長到 200 MB 后觸發一個 200 毫秒的 GC 周期,而不是增長到 1 GB 后觸發一個 1500 毫秒的 GC 周期,則使用較小的堆效果會好得多,因為應用程序無論如何都不需要較大的內存占用空間。這當然是假設最大的堆大小始終滿足用于長期分配所需的堆空間量。此技巧與?第 2 部分的技巧 CPU012?相同,但現在是集中于應用程序的內存占用空間,而不只是集中于應用程序的性能。
即使分配相當迅速,固定大小的堆通常也工作得很好。但是如果這些臨時對象的大小通常相當大,則堆會很快變得零碎,從而導致假性 OOM。不適合使用技巧 MEM001?的另一個場景是固定 (Pinned) 對象正在導致碎片的情況。如果必須將對象固定在堆中,則將它們分配在堆中盡可能低的位置是有幫助的。但是除非非做不可,否則 Java 不會收集垃圾,因此只要有堆可用,就不會觸發任何 GC 周期,并且這會轉化為以導致碎片的方式分配固定對象。
較新版本的 Java 能夠執行更好的碎片管理,并且可以使用新的開關來調整固定集群的大小(請參見 -Xk 和 –Xp)。但是如果您遇到堆碎片,技巧 MEM002?也許能滿足您的所有需要。在許多情況下,堆擴展和收縮能夠比壓縮周期更好地消除堆中的空隙。堆碎片會嚴重影響應用程序的可伸縮性,技巧 MEM002 是在這些情況下使用的理想調整。
GC 活動
下面是基于 verbosegc 輸出的簡單指示信息。有關更多詳細信息,請參閱“Fine-tuning Java Garbage Collection Performance”。
- 如果您在使用技巧 MEM002,并且在應用程序穩定時觀察到太多的 GC,請參見技巧 MEM007。您可能還希望嘗試一下技巧 MEM001,并確定它是否有幫助。
- 如果觀察到堆擴展或收縮得太頻繁,可以使用技巧 MEM001?來同時消除收縮和擴展。技巧 MEM005?將消除任何堆收縮。
- 如果 GC 周期中的標記時間太高,您應該嘗試?MEM006。這也可能是由于“標記堆棧溢出 (Mark Stack Overflow)”所導致的。
- 如果 GC 周期不是由于“分配故障 (Allocation Failure)”所導致的,可以使用技巧 MEM007。不過分布式 GC 調用不會受到此設置的影響。
- 如果 verbosegc 中指示了過多的壓縮,這可能與某個大小調整不足的堆有關。
本機堆
如果應用程序的本機代碼發出多個小請求,則使用技巧 MEM008?也許會獲得性能提升。但是本機堆調整的最重要部分是確保每一次本機堆分配都與相應的回收相匹配。可以使用?svmon?監視本機堆,并且您可能希望設置 IBM_JAVA_MMAP_JAVA_HEAP=true,以便更清楚地區分 Java 堆和本機堆。除了確保應用程序不會在運行時耗盡本機堆以外,通常沒有多少針對本機堆的性能優化余地。
回頁首
一般技巧集合
下文將把 Java 的命令行參數(在 class/jar 文件名稱之前指定)稱為“開關”。例如,命令行?java -mx2g hello?具有單個開關?-mx2g。
技巧 MEM001:固定大小的堆
通過同時為初始 (-Xms) 和最大 (-Xmx) Java 堆大小指定相同的值,從而創建固定大小的 Java 堆。指定的值應該足夠高到不會導致 OOM,同時要足夠低到不會顯著增加 GC 周期時間。
請注意:指定固定大小的堆意味著您將不能使用?-Xminf/-Xmaxf/-Xmine/-Xmaxe?來微調 GC 特征。固定大小的堆在許多情況下還容易導致碎片。
技巧 MEM002:可變大小的堆
通過為?-Xms?和?-Xmx?指定不同的值,或者僅指定?-Xmx,從而創建可變大小的 Java 堆。指定的值應該足夠高以避免 OOM,但是應該進行調整以避免過多的堆收縮或擴展。
請注意:如果優化不當,使用可變大小的堆會產生嚴重的性能影響。
技巧 MEM003:快速的堆增長
使用高于缺省值 (1 MB) 的?-Xmine?值。這將允許 Java 堆的最小擴展變得更迅速。例如,?-Xmine5m?將允許堆一次增長 5 MB(或更多,最多可達?-Xmaxe)。
請注意:-Xmine?只是在進行堆擴展時發揮作用的若干因素之一。有關堆擴展的更多信息,請參見 Diagnostics Guides。
技巧 MEM004:受控的堆增長
使用與缺省值 (0) 不同的?-Xmaxe?值。這會強制將 Java 堆的最大擴展保持在指定的限制之內。例如,-Xmaxe2m?將強制堆在一個周期中的增長不能超過 2MB。
請注意:?-Xmaxe?只是在進行堆擴展時發揮作用的若干因素之一。有關堆擴展的更多信息,請參見位于?IBM developer kits - diagnosis documentation?的 Diagnostics Guides。
技巧 MEM005:禁用堆收縮
要禁用堆收縮,可以使用?-Xmaxf1,此開關將最大空閑堆百分比設置為 100%。
請注意:這將強制堆只能增長,如果堆具有固定大小,則此開關不起作用。
技巧 MEM006:使用并發標記 (Concurrent Mark)
使用開關?-Xgcpolicy:optavgpause?以啟用并發標記。
請注意:對于 CPU 密集型應用程序,此設置可能會影響性能。
技巧 MEM007:禁用顯式的 GC 調用
使用開關?-Xdisableexplicitgc?禁用任何?System.gc()?調用以避免觸發 GC。
請注意:確保您的應用程序功能不會受到此開關的影響。
技巧 MEM008:優化本機堆分配
設置環境變量:
export MALLOCTYPE=buckets以切換到基于 Bucket 的本機堆模型。
請注意:Java 堆分配不受此開關的影響。而且,如果使用不當,此開關會影響應用程序的性能。
回頁首
總結
本文向您介紹了如何使用 AIX 工具進行 Java 性能監視,并提供了可用來優化應用程序的內存使用的常用調整列表。本系列中的下一篇文章將討論“AIX 上的 Java 應用程序的網絡和磁盤 I/O 調整”。
參考資料
學習
- 本系列文章的其他部分:
- 第 1 部分
- 第 2 部分
- 第 4 部分
- 第 5 部分
轉載于:https://www.cnblogs.com/anruy/p/4919403.html
總結
以上是生活随笔為你收集整理的最大化 AIX 上的 Java 性能,第 3 部分: 更多就是更好的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java虚拟机10:类加载器
- 下一篇: SharePoint 2013 Nint