您是否应该信任JVM中的默认设置?
如今,JVM被認為是智能的。 預期不會進行太多配置–只需設置要在啟動腳本中使用的最大堆,您就可以進行了。 所有其他默認設置都很好。 大概我們當中有些人誤以為。 實際上,在運行時期間發生了很多事情,無法自動調整性能,因此,在我最近面對的一個案例研究中,我將帶您逐步了解要調整的內容和時間。
但是在討論案例本身之前,先介紹了有關JVM內部的一些背景知識。 以下所有內容均與Oracle Hotspot 7有關。 其他供應商或更早版本的Hotspot JVM很有可能帶有不同的默認值。
JVM默認選項
第一站 :JVM嘗試確定是否 它正在客戶端環境的服務器上運行。 它通過查看體系結構和OS組合來做到這一點。 簡單總結:
| 建筑 | CPU /內存 | 操作系統 | 默認 |
| i586 | 任何 | 微軟視窗 | 客戶 |
| AMD64 | 任何 | 任何 | 服務器 |
| 64位SPARC | 任何 | 的Solaris | 服務器 |
| 32位SPARC | 2個以上內核和> 2GB RAM | 的Solaris | 服務器 |
| 32位SPARC | 1核或<2GB RAM | 的Solaris | 客戶 |
| i568 | 2個以上內核和> 2GB RAM | Linux或Solaris | 服務器 |
| i568 | 1核或<2GB RAM | Linux或Solaris | 客戶 |
例如,如果您在32位Linux上的Amazone EC2 m1.medium實例上運行,則默認情況下,您將被視為在客戶端計算機上運行。
這很重要,因為JVM在客戶端和服務器上的優化方式完全不同-在客戶端計算機上,它嘗試減少啟動時間,并在啟動過程中跳過一些優化。 在服務器環境上,會犧牲一些啟動時間來稍后實現更高的吞吐量。
第二組默認值 :堆大小。 如果您的環境被認為是根據先前準則確定的服務器,則分配的初始堆將是計算機上可用內存的1/64。 在4G機器上,這意味著您的初始堆大小將為64MB。 如果在極低的內存條件下(<1GB)運行,它可能會更小,但是在這種情況下,我將嚴重懷疑您在做任何合理的事情。 在這個千年中,還沒有看到內存少于千兆字節的服務器。 如果有的話,我會提醒您,如今1 GB的DDR成本不到20美元……
但這將是初始堆大小。 最大堆大小將是可用總內存的?或1GB中的最小值。 因此,在我們的1.7GB Amazon EC2 m1.small實例中,可用于JVM的最大堆大小約為435MB。
下一步 :使用默認垃圾收集器。 如果認為您正在客戶端JVM上運行,則JVM所應用的默認值為串行GC( -XX:+ UseSerialGC )。 在服務器級計算機上(同樣,請參見第一部分),默認值為并行GC( -XX:+ UseParallelGC )。
默認值還有很多其他事情,例如PermGen的大小,不同的世代調整,GC暫停限制等。但是為了使帖子的大小受到控制,請堅持使用上述配置。 對于好奇的用戶-您可以從以下材料中進一步了解默認值:
- http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
- http://docs.oracle.com/javase/7/docs/technotes/guides/vm/gc-ergonomics.html
- http://docs.oracle.com/javase/7/docs/technotes/guides/vm/server-class.html
案例分析
現在讓我們看一下案例研究的行為。 以及我們是否應該憑借決策信任JVM還是跳入我們自己。
我們手頭的應用程序是一個問題跟蹤器。 即JIRA 。 這是一個在后端具有關系數據庫的Web應用程序。 部署在Tomcat上。 在我們的一種客戶端環境中表現不佳。 并不是由于任何泄漏,而是由于部署中的不同配置問題。 由于GC暫停時間特別長,這種行為不當的配置導致吞吐量和延遲方面的重大損失。 我們設法幫助了客戶,但是出于隱私考慮,我們將不在此處介紹確切的詳細信息。 但是案例很好,因此我們繼續下載了JIRA ,以演示我們從此實際案例研究中發現的一些概念。
Atlassian的特別之處在于,這些家伙已經附帶了一些打包好的負載測試 。 因此,我們有一個基準可用于我們的配置。
我們仔細拆箱了我們新收購的JIRA的包裝,并將其安裝在64位Linux Amazon EC2 m1.medium實例上。 并進行捆綁測試 。 無需更改默認值。 Atlassian小組將其設置為-Xms256m -Xmx768m -XX:MaxPermSize = 256m
在每次運行期間,我們使用-XX:+ PrintGCTimeStamps -Xloggc:/tmp/gc.log -XX:+ PrintGCDetails收集了GC日志,并在GCViewer的幫助下分析了此統計信息。
結果實際上還不錯。 我們將測試運行了一個小時,然后由于垃圾收集暫停而損失了僅151秒 。 占總運行時間的4.2%。 在最壞的情況下,gc的暫停時間為2秒 。 因此,GC暫停會影響此特定應用程序的吞吐量和延遲。 但不要太多。 但是足以作為本案例研究的基準–在我們的實際客戶中,GC暫停時間長達25秒。
挖掘GC日志浮出了水面。 Full GC的大多數運行都是由PermGen大小隨時間擴展而引起的。 日志顯示,測試期間總共使用了大約155MB的PermGen。 因此,通過在啟動腳本中添加-XX:PermSize = 170m ,我們將PermGen的初始大小增加到比實際使用的大小更多。 這使總的暫停時間從151秒減少到134秒 。 并將最大等待時間從2,000ms減少到1300ms 。
然后我們發現了完全出乎意料的事情。 我們的JVM使用的GC實際上是串行GC。 如果您認真地遵循了我們的文章,則情況并非如此-64位Linux機器應始終被視為服務器級機器,并且所使用的GC應該是并行GC。 但顯然并非如此。 到目前為止,我們最好的猜測是–即使JVM以服務器模式啟動,它仍然會根據可用的內存和內核來選擇所使用的GC。 由于此m1.medium實例具有3.75GB內存,但只有一個虛擬內核,因此所選的GC仍是串行的。 但是,如果你們對這個話題有更多的見解,我們渴望找到更多。
盡管如此,我們將算法更改為-XX:+ UseParallelGC并重新運行測試。 結果–累積的停頓進一步減少到92秒 。 最壞情況的延遲也減少到了1200ms 。
對于最終測試,我們嘗試嘗試并發標記和掃描模式。 但是該算法對我們完全失敗了–暫停時間增加到300秒,延遲增加到5,000毫秒以上。 在這里,我們放棄了,決定叫它一個晚上。
因此,僅使用兩個JVM啟動參數并花費幾個小時來配置和解釋結果,我們就有效地提高了應用程序的吞吐量和延遲。 絕對數字聽起來并不令人印象深刻– GC暫停從151秒減少到92秒,最壞情況下的延遲從2,000ms減少到1200ms ,但是請記住,這只是一個只有兩個配置設置的小型測試。 從%的角度來看–嘿,我們都提高了與GC暫停相關的吞吐量,并將延遲減少了40% !
無論如何,我們現在再有一個案例向您展示,性能調整就是關于設定目標,進行測量,調整和重新測量。 也許您和我們一樣幸運,只需更改兩個配置選項就可以使您的用戶更快樂40%……
參考: 您是否應該信任JVM中的默認設置? 由我們的JCG合作伙伴 Nikita Salnikov Tarnovski在Plumbr Blog博客上獲得。
翻譯自: https://www.javacodegeeks.com/2012/12/should-you-trust-the-default-settings-in-jvm.html
總結
以上是生活随笔為你收集整理的您是否应该信任JVM中的默认设置?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华硕三款全新笔记本发布 搭载赛扬N450
- 下一篇: 中国用户增速显著 多邻国即将推出进阶英文