JVM堆內存監測的一種方式,性能調優依舊任重道遠

上月,由極客邦、InfoQ和聽雲聯合主辦2016 APMCon中國應用性能管理大會圓滿落下帷幕。會上,Java冠軍Martijn Verburg進行了一場Java and the Machine的分享,討論了爲何數據分析相當重要。他有着十多年Java經驗,目前是創業公司jClarity的CEO,jClarity是一款採用統計和機器學習來探究性能問題根源的方案。會後,InfoQ還專訪Martijn以進一步瞭解溝通。程序員

JVM堆內存及一種監測方式數組

在討論Martijn的團隊如何進行堆內存監測以前,咱們先回顧下JVM的工做機制。JVM是一種對計算機的抽象行爲,是它保證了Java程序的運行。每個運行的Java程序都對應着一個JVM實例。JVM的結構以下圖緩存

Java把內存劃分紅兩種:一種是棧內存,一種是堆內存。棧與堆都是Java用來在RAM中存放數據的地方。與C++不一樣,Java自動管理棧和堆,程序員不能直接地設置棧或堆。堆內存用來存放由new建立的對象和數組。在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。即每個Java應用都惟一對應一個JVM實例,每個實例惟一對應一個堆。網絡

自從Java1.3以後,Oracle出臺的JRE就包含了一個名爲HotSpot的JVM,它將Java的對象按照世代管理並存放在堆的內存中,以期能夠更好地管理堆內存中的對象,包括內存的分配以及回收。共劃分爲三個世代:年輕代、老年代、永久代。永久代(Permanent Generation)則存放的是類的定義和相關元數據。可是在Java 8中該區域已經被移除。專家分析稱此舉更有利於性能調優。框架

現有版本保留的兩個世代爲年輕代(Young Generation)和老年代(Old Generation)。年輕代爲建立的短時間對象,失效以後很快會被垃圾回收。該區又被劃分爲Eden和兩個Survivor區域。老年代存放的多數爲存活時間較長的對象。其中堆的各個區之間的比例分配有默認值,可是能夠經過參數指定。垃圾回收GC分爲兩種Minor GC、Full GC;Minor GC發生頻繁,可是僅針對年輕代。機器學習

垃圾回收以後會對JVM形成必定影響,年老代的佔用空間曲線以下圖:工具

20160919051139734.png

上圖來自jClarity對堆的年老代佔用空間監測圖,jClarity是一款Java的性能監測工具,由Martijn、另外兩位資深Java專家和一位機器學習工程師共同實現。Martijn分享了jClarity如何進行堆內存的監測他首先列舉了垃圾回收以後,一般狀況下堆內存中的老年代(Tenured/Old Generation)的內存佔用曲線,通常而言,會前後發生兩個陡然增長的高峯。性能

基於以上現象的信息, Martijn和他的團隊開展了他們的性能監測方案。Martijn他們採起的作法是先收集儘量多的點,而後只保留老年代的數據,對垃圾回收形成的兩個脈衝式波峯進行了過濾,這時再對這些真正的數據點進行建模抽象,最後保留出了一條曲線。學習

20160919051139928.jpg

這條曲線就是對監測的Java程序內存的變化趨勢,該曲線會以50Mb/小時的速率增加,據此推測出什麼時候發生內存泄露。jClarity還有不少其餘功能,相比於傳統的指標統計方式,Martijn稱團隊產品的特色在於:高級統計+機器學習。大數據

Java和JVM面臨怎樣的困境?

Martijn還分享了他對Java現狀和JVM性能調優的擔心和思考,他認爲如今Java和JVM面臨下面五個問題:

程序只能寫一次,可是卻要在各類地方跑
這意味着Java須要解決來自各方面的差別:
CPU的差別——何時能夠放入緩存中呢?何時能夠被從新排序呢?
文件系統的差別——不一樣操做系統對文件的符號連接有不一樣機制
顯示設備的差別——硬件更新速度很快,幾乎沒法追上
原生庫支持的差別——很難存在全部的原生庫皆一致的狀況
操做系統線程管理的差別——線程的規劃方式很不相同
此外,面對正在迅速發展AR、VR,Java缺乏真正的GPU支持,這一樣是一個短板。模型對存儲的強需求
JVM太謹慎了,他總想作對的事情,可是爲此不得不在性能上的妥協。鎖機制增強了正確性,可是在性能上付出了巨大的代價。
鎖機制決定了Java序列化的工做區。由於Java對象序列化不只保留一個對象的數據,並且遞歸保存對象引用的每一個對象的數據。能夠將整個對象層次寫入字節流中,能夠保存在文件中或在網絡鏈接上傳遞。利用對象序列化能夠進行對象的"深複製",即複製對象自己及引用的對象自己。序列化一個對象可能獲得整個對象序列。結合利特爾法則(Little's law)和阿姆達爾定律(Amdahl’s law),這種方式影響到了並行存儲的性能。垃圾回收機制下的擴展性
JVM須要維護活的對象,這意味着:堆須要更大空間以存放更多的對象;垃圾回收機制須要花時間去辨認哪些是活的對象;在垃圾回收過程當中須要耗費時間進行堆的維護。
其次,Java中沒有值類型(value type 和reference type的區別),沒有結構體:這形成了大量低效能的對象建立。容器和虛擬化的支持
Java無法獲取虛擬化數據。Java和JVM的思考模式是創建在物理裸機上的,信息缺失的狀況下會進行一些錯誤選擇。而且,沒有對Docker等容器技術的直接支持,這是新時代的另外一個短板。

關於Java和JVM性能調優的思考

除了上述的總體層面的挑戰以外,Java的性能自己又很難監測。必須結合其餘的指標來間接把控:CPU,內存;接口I/O,網絡I/O;虛擬化和容器化等。但是一旦得到了這些指標,又帶來了大數據的問題。由於咱們盲目地收集了過多的數據,這形成了巨大的性能損害,由於收集、傳輸、存儲每一個過程都是一種消耗。

要記住目的是分析得到信息,而不是收集指標。可是從指標數據到提煉出有用信息很難,Martijn認爲要作好性能調優須要明白規律和原理(如上文所說起的Little's law和Amdahl’s law),理解硬件、操做系統、Java工做原理還要讀懂代碼,而且已經有了基於大量數據的分析經驗。

Martijn認爲將來性能監測的趨勢是高級統計和機器學習方式的結合,這種模式將取代傳統的單純指標採集模式。

對話Martijn

InfoQ:一般來講,JVM層面的APM工具並不適用於生產環境。那爲何您稱jClarity能夠?

Martijn:與其餘工具相比,首先在JVM層面上咱們獲取更少的數據。 jClarity之因此能夠更少地獲取,是由於咱們採用了機器學習的辦法,辨別除了哪些纔是真正有用的數據,咱們稱之爲「信號」,餘下的數據咱們稱之爲噪聲。在收集數據過程當中,一旦檢測噪聲,咱們馬上對過濾。

其次咱們還會盡量避免從JVM自己獲取數據,取而代之從JVM的日誌中(如GC日誌、safepoint日誌)等獲取數據。目前咱們還在和Google合做,在嘗試怎樣從JVM以外,得到更多的信息。可是,整體而言,jClarity用於生產環境是沒有問題的。

InfoQ:爲何還要收集JMV的日誌以外的數據呢?

Martijn:由於JVM日誌並不能給咱們足夠的信息。你能夠從JVM日誌中得到,或者經過JMX接口。不過,你也能夠經過設定一個Java或者原生的agent來得到更特定的信息;但這是一種太重的作法,一般而言並不推薦。不少人包括Oracle在內都意識到了這個問題,可是徹底解決有待時日。

InfoQ:數據收集的過程是否對用戶來講是透明的呢?是否支持ASM字節碼織入技術呢?

Martijn:是的。底層的數據,咱們不只僅從Java中得到,還會從操做系統中獲取。好比,當用戶在Linux上運行,那麼他還會看見收集到的CPU、內存使用率等信息。

對於有特殊需求的用戶,他們是能夠採用ASM,此外咱們也提供一個開發階段使用的庫,可是建議用戶當心使用,由於很容易會產生操做不當。

InfoQ:數據收集以後,jClarity根據機器學習出來的成果進行了處理,可否和咱們分享下機器學習的事情?

Martijn:在我被許可的範圍內,由於機器學習是咱們的機密模塊。不過我能夠分享這裏很是重要的一點:咱們有大量多環境的用戶數據,用戶們的程序也是多種多樣,如網頁程序、視頻流程序等;咱們會施加不一樣的網絡壓力,這樣咱們獲得了數據訓練集。這些數據集是專家人工操做產生的。同時在實時收集處理數據的時候,咱們也會進行機器學習。好比發現Java性能受到影響,機器學習認定最重要一個因素就是GC垃圾回收,那麼接下來就是調查GC;若是GC沒有問題,那麼就會在機器學習成果的指引下開始下一個因素的勘察。整體而言,機器學習的決定了發生問題時排查的路徑。

機器學習這部分的研發工做咱們作了兩年,也很感謝這些用戶爲咱們付費而且贊成咱們這樣作。咱們的一些用戶擁有超大規模,這種狀況下,已經沒法期望人工對數據進行分析;因此對於咱們來講,機器學習是惟一的出路,惟一的方式可讓咱們繼續支持用戶。

InfoQ:APM工具的挑戰有哪些?

Martijn:首先是IT環境複雜性的加重。你的代碼再也不跑在你本身的機器和環境中,你沒法作到100%肯定你的程序和代碼是怎樣被管理的。另一個挑戰就是網絡是不穩定的。在有線光纖專用網絡上,你不須要和其餘人共享;可是在公用雲上,網路流量徒增的狀況時有發生,開發人員不得不在代碼層面上面對這個挑戰,APM工具也必須理解並迎面這個問題。目前,尚未哪一個APM工具能夠勝任這兩個挑戰,因此目前這仍是一個很是有趣有待研究的領域。

InfoQ:您在演講中有提到,Java創立之初硬件並無今天這樣複雜,那麼是否是說Java已經再也不適合今天了呢?你認爲Java語言的獨特魅力在哪裏呢?

Martijn:「Java將死」的留言每一年都有。Java語言這麼多年,常常遇到新興語言的挑戰,可是新興語言很快就會發現本身也處於一個相似的局面。我認爲Java依然是一個合適的語言,JVM正在嘗試在各類狀況下都作到最好。咱們能夠看到Go、RUST語言變得愈來愈火,可是Oracle正在很是努力地攻克這點,包括更頻繁地發佈Java,也很想快速地跟上包括支持GPU、其餘新型硬件設備等。因此說挑戰是有的,可是使人高興的是不少大公司都願意繼續努力提升Java。我但願Java社區能夠更開放些,能夠歡迎更多的公司參與,好比阿里巴巴,阿里巴巴多是全球上最大的重度Java研發羣。

Java的魅力在於易寫性、強可讀性。不像如今的一些語言,你不須要嚴格地按照某種規範來寫代碼。就算代碼寫完五年以後,新來的人依然能夠讀懂代碼。還有就是Java豐富的框架和庫。甚至這些框架和庫的魅力能夠和Java語言自己相媲美。

 

https://yq.aliyun.com/articles/145758?utm_content=m_26867

相關文章
相關標籤/搜索