精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

JVM堆內(nèi)存監(jiān)測的一種方式,性能調(diào)優(yōu)依舊任重道遠

責任編輯:editor006

作者:木環(huán)

2016-09-19 17:11:00

摘自:INFOQ

上月,由極客邦、InfoQ和聽云聯(lián)合主辦2016 APMCon中國應(yīng)用性能管理大會圓滿落下帷幕。Martijn認為未來性能監(jiān)測的趨勢是高級統(tǒng)計和機器學習方式的結(jié)合,這種模式將取代傳統(tǒng)的單純指標采集模式。

上月,由極客邦、InfoQ和聽云聯(lián)合主辦2016 APMCon中國應(yīng)用性能管理大會圓滿落下帷幕。會上,Java冠軍Martijn Verburg進行了一場Java and the Machine的分享,討論了為什么數(shù)據(jù)分析至關(guān)重要。他有著十多年Java經(jīng)驗,目前是創(chuàng)業(yè)公司jClarity的CEO,jClarity是一款采用統(tǒng)計和機器學習來探究性能問題根源的方案。會后,InfoQ還專訪Martijn以進一步了解溝通。

JVM堆內(nèi)存及一種監(jiān)測方式

在討論Martijn的團隊如何進行堆內(nèi)存監(jiān)測之前,我們先回顧下JVM的工作機制。JVM是一種對計算機的抽象行為,是它保證了Java程序的運行。每一個運行的Java程序都對應(yīng)著一個JVM實例。JVM的結(jié)構(gòu)如下圖

Java把內(nèi)存劃分成兩種:一種是棧內(nèi)存,一種是堆內(nèi)存。棧與堆都是Java用來在RAM中存放數(shù)據(jù)的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設(shè)置棧或堆。堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組。在堆中分配的內(nèi)存,由Java虛擬機的自動垃圾回收器來管理。即每一個Java應(yīng)用都唯一對應(yīng)一個JVM實例,每一個實例唯一對應(yīng)一個堆。

自從Java1.3之后,Oracle出臺的JRE就包含了一個名為HotSpot的JVM,它將Java的對象按照世代管理并存放在堆的內(nèi)存中,以期可以更好地管理堆內(nèi)存中的對象,包括內(nèi)存的分配以及回收。共劃分為三個世代:年輕代、老年代、永久代。永久代(Permanent Generation)則存放的是類的定義和相關(guān)元數(shù)據(jù)。但是在Java 8中該區(qū)域已經(jīng)被移除。專家分析稱此舉更有利于性能調(diào)優(yōu)。

現(xiàn)有版本保留的兩個世代為年輕代(Young Generation)和老年代(Old Generation)。年輕代為創(chuàng)建的短期對象,失效之后很快會被垃圾回收。該區(qū)又被劃分為Eden和兩個Survivor區(qū)域。老年代存放的多數(shù)為存活時間較長的對象。其中堆的各個區(qū)之間的比例分配有默認值,但是可以通過參數(shù)指定。垃圾回收GC分為兩種Minor GC、Full GC;Minor GC發(fā)生頻繁,但是僅針對年輕代。

垃圾回收之后會對JVM造成一定影響,年老代的占用空間曲線如下圖:

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

基于以上現(xiàn)象的信息, Martijn和他的團隊開展了他們的性能監(jiān)測方案。Martijn他們采取的做法是先收集盡可能多的點,然后只保留老年代的數(shù)據(jù),對垃圾回收造成的兩個脈沖式波峰進行了過濾,這時再對這些真正的數(shù)據(jù)點進行建模抽象,最后保留出了一條曲線。

這條曲線就是對監(jiān)測的Java程序內(nèi)存的變化趨勢,該曲線會以50Mb/小時的速率增長,據(jù)此推測出何時發(fā)生內(nèi)存泄露。jClarity還有很多其他功能,相比于傳統(tǒng)的指標統(tǒng)計方式,Martijn稱團隊產(chǎn)品的特點在于:高級統(tǒng)計+機器學習。

Java和JVM面臨怎樣的困境?

Martijn還分享了他對Java現(xiàn)狀和JVM性能調(diào)優(yōu)的擔憂和思考,他認為現(xiàn)在Java和JVM面臨下面五個問題:

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

關(guān)于Java和JVM性能調(diào)優(yōu)的思考

除了上述的整體層面的挑戰(zhàn)之外,Java的性能本身又很難監(jiān)測。必須結(jié)合其他的指標來間接把控:CPU,內(nèi)存;接口I/O,網(wǎng)絡(luò)I/O;虛擬化和容器化等。可是一旦獲得了這些指標,又帶來了大數(shù)據(jù)的問題。因為我們盲目地收集了過多的數(shù)據(jù),這造成了巨大的性能損害,因為收集、傳輸、存儲每個過程都是一種消耗。

要記住目的是分析獲得信息,而不是收集指標。但是從指標數(shù)據(jù)到提煉出有用信息很難,Martijn認為要做好性能調(diào)優(yōu)需要明白規(guī)律和原理(如上文所提及的Little's law和Amdahl’s law),理解硬件、操作系統(tǒng)、Java工作原理還要讀懂代碼,并且已經(jīng)有了基于大量數(shù)據(jù)的分析經(jīng)驗。

Martijn認為未來性能監(jiān)測的趨勢是高級統(tǒng)計和機器學習方式的結(jié)合,這種模式將取代傳統(tǒng)的單純指標采集模式。

對話Martijn

InfoQ:通常來說,JVM層面的APM工具并不適用于生產(chǎn)環(huán)境。那為什么您稱jClarity可以?

Martijn:與其他工具相比,首先在JVM層面上我們獲取更少的數(shù)據(jù)。 jClarity之所以可以更少地獲取,是因為我們采用了機器學習的辦法,辨別除了哪些才是真正有用的數(shù)據(jù),我們稱之為“信號”,余下的數(shù)據(jù)我們稱之為噪聲。在收集數(shù)據(jù)過程中,一旦檢測噪聲,我們立刻對過濾。

其次我們還會盡可能避免從JVM本身獲取數(shù)據(jù),取而代之從JVM的日志中(如GC日志、safepoint日志)等獲取數(shù)據(jù)。目前我們還在和Google合作,在嘗試怎樣從JVM之外,獲得更多的信息。但是,總體而言,jClarity用于生產(chǎn)環(huán)境是沒有問題的。

InfoQ:為什么還要收集JMV的日志之外的數(shù)據(jù)呢?

Martijn:因為JVM日志并不能給我們足夠的信息。你可以從JVM日志中獲得,或者通過JMX接口。不過,你也可以通過設(shè)定一個Java或者原生的agent來獲得更特定的信息;但這是一種過重的做法,通常而言并不推薦。很多人包括Oracle在內(nèi)都意識到了這個問題,但是完全解決有待時日。

InfoQ:數(shù)據(jù)收集的過程是否對用戶來說是透明的呢?是否支持ASM字節(jié)碼織入技術(shù)呢?

Martijn:是的。底層的數(shù)據(jù),我們不僅僅從Java中獲得,還會從操作系統(tǒng)中獲取。比如,當用戶在Linux上運行,那么他還會看見收集到的CPU、內(nèi)存使用率等信息。

對于有特殊需求的用戶,他們是可以采用ASM,此外我們也提供一個開發(fā)階段使用的庫,但是建議用戶小心使用,因為很容易會產(chǎn)生操作不當。

InfoQ:數(shù)據(jù)收集之后,jClarity根據(jù)機器學習出來的成果進行了處理,能否和我們分享下機器學習的事情?

Martijn:在我被許可的范圍內(nèi),因為機器學習是我們的機密模塊。不過我可以分享這里非常重要的一點:我們有大量多環(huán)境的用戶數(shù)據(jù),用戶們的程序也是多種多樣,如網(wǎng)頁程序、視頻流程序等;我們會施加不同的網(wǎng)絡(luò)壓力,這樣我們得到了數(shù)據(jù)訓練集。這些數(shù)據(jù)集是專家人工操作產(chǎn)生的。同時在實時收集處理數(shù)據(jù)的時候,我們也會進行機器學習。比如發(fā)現(xiàn)Java性能受到影響,機器學習認定最重要一個因素就是GC垃圾回收,那么接下來就是調(diào)查GC;如果GC沒有問題,那么就會在機器學習成果的指引下開始下一個因素的勘察。總體而言,機器學習的決定了發(fā)生問題時排查的路徑。

機器學習這部分的研發(fā)工作我們做了兩年,也很感謝這些用戶為我們付費并且同意我們這樣做。我們的一些用戶擁有超大規(guī)模,這種情況下,已經(jīng)無法指望人工對數(shù)據(jù)進行分析;所以對于我們來說,機器學習是唯一的出路,唯一的方式可以讓我們繼續(xù)支持用戶。

InfoQ:APM工具的挑戰(zhàn)有哪些?

Martijn:首先是IT環(huán)境復雜性的加劇。你的代碼不再跑在你自己的機器和環(huán)境中,你無法做到100%確定你的程序和代碼是怎樣被管理的。另外一個挑戰(zhàn)就是網(wǎng)絡(luò)是不穩(wěn)定的。在有線光纖專用網(wǎng)絡(luò)上,你不需要和其他人共享;但是在公用云上,網(wǎng)路流量徒增的情況時有發(fā)生,開發(fā)人員不得不在代碼層面上面對這個挑戰(zhàn),APM工具也必須理解并迎面這個問題。目前,還沒有哪個APM工具可以勝任這兩個挑戰(zhàn),所以目前這還是一個非常有趣有待研究的領(lǐng)域。

InfoQ:您在演講中有提到,Java創(chuàng)立之初硬件并沒有今天這樣復雜,那么是不是說Java已經(jīng)不再適合今天了呢?你認為Java語言的獨特魅力在哪里呢?

Martijn:“Java將死”的留言每年都有。Java語言這么多年,經(jīng)常遇到新興語言的挑戰(zhàn),但是新興語言很快就會發(fā)現(xiàn)自己也處于一個類似的局面。我認為Java依然是一個合適的語言,JVM正在嘗試在各種情況下都做到最好。我們可以看到Go、RUST語言變得越來越火,但是Oracle正在非常努力地攻克這點,包括更頻繁地發(fā)布Java,也很想快速地跟上包括支持GPU、其他新型硬件設(shè)備等。所以說挑戰(zhàn)是有的,但是令人高興的是很多大公司都愿意繼續(xù)努力提高Java。我希望Java社區(qū)可以更開放些,可以歡迎更多的公司參與,比如阿里巴巴,阿里巴巴可能是全球上最大的重度Java研發(fā)群。

Java的魅力在于易寫性、強可讀性。不像現(xiàn)在的一些語言,你不需要嚴格地按照某種規(guī)范來寫代碼。就算代碼寫完五年之后,新來的人依然可以讀懂代碼。還有就是Java豐富的框架和庫。甚至這些框架和庫的魅力可以和Java語言本身相媲美。

參考文章:https://en.wikipedia.org/wiki/Java_virtual_machine

鏈接已復制,快去分享吧

企業(yè)網(wǎng)版權(quán)所有?2010-2024 京ICP備09108050號-6京公網(wǎng)安備 11010502049343號

  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 安宁市| 阿瓦提县| 扶沟县| 冀州市| 日土县| 南陵县| 瓦房店市| 巢湖市| 锦州市| 工布江达县| 集贤县| 锡林浩特市| 呼和浩特市| 林甸县| 新乐市| 河源市| 新和县| 莱西市| 琼海市| 望谟县| 保山市| 湘潭市| 化州市| 衡阳市| 云梦县| 石渠县| 乐山市| 濉溪县| 张北县| 吉隆县| 武夷山市| 绥芬河市| 玉树县| 靖江市| 拉萨市| 司法| 如东县| 益阳市| 印江| 石屏县| 蒲城县|