原文鏈接:https://www.infoq.com/news/2017/03/java-epsilon-gc
InfoQ中文翻譯:http://www.infoq.com/cn/news/2017/03/java-epsilon-gc?utm_source=infoq_en&utm_medium=link_on_en_item&utm_campaign=item_in_other_langs
在RedHat負(fù)責(zé)OpenJDK開發(fā)和性能優(yōu)化的Aleksey Shipil?v不久前發(fā)表了一份新的JEP草案咕宿,草案中計劃將推出新一代不會真正回收內(nèi)存的垃圾回收器(GC)油讯。此次的回收器計劃主要目的包括兩個方面曼库,給JVM的實(shí)現(xiàn)者和研究者在GC方面更多的幫助,以及大幅減少應(yīng)用運(yùn)行時產(chǎn)生的“內(nèi)存垃圾”。雖然后者只是計劃中的一小部分,但是顯然他更受公眾的關(guān)注。如果JEP繼續(xù)照計劃發(fā)展,新的GC將和現(xiàn)有的共存巍举,并且只有在指定使用新版GC后才會生效。
垃圾回收器和Java性能是一個復(fù)雜且龐大的話題凝垛,因此InfoQ特地請來了兩位Java Champions中的性能專家Martijn Verburg 和 Kirk Pepperdine懊悯,來為我們作出更加客觀準(zhǔn)確的分析講解。同時我們也會采訪Remko Popma——實(shí)現(xiàn)Log4j 的garbage-free功能的領(lǐng)導(dǎo)者梦皮,向他了解相關(guān)功能的實(shí)現(xiàn)細(xì)節(jié)炭分。Verburg 和 Popma都認(rèn)為無操作GC(或者稱之為Epsilon GC)的主要受益者是GC開發(fā)者和性能研究人員。Epsilon
GC可以作為一個可控的選項剑肯,來測量比較和其他垃圾回收器的性能差別捧毛。舉個簡單的例子,我們可以讓應(yīng)用程序運(yùn)行在無操作GC上來較少GC的性能開銷(在排除其他內(nèi)存申請和突發(fā)情況的前提下)让网。如果同樣的應(yīng)用程序在除了GC算法以外都相同的工作環(huán)境上運(yùn)行呀忧,性能上的差異就能直接反映出GC算法對這個應(yīng)用的影響。這將讓GC開發(fā)者和性能研究人員通過更純粹的方式理解GC的行為溃睹。
“我認(rèn)為這是對精確測量JVM個部分性能跨出的一大步(比如已有的JIT C1/C2 編譯器而账,可能會被轉(zhuǎn)移到Graal 等)。這將讓JVM存活得更久因篇∨⒎”Martijn Verburg說笔横。
在另一方面,Epslion GC可以讓性能要求嚴(yán)格的應(yīng)用從中收益铛碑。存在某些類似前文提到的Log4j這樣的應(yīng)用或者庫狠裹,它們通過一些方式使得運(yùn)行中不會產(chǎn)生需要回收的內(nèi)存,因此也不需要垃圾回收器汽烦。對于這種應(yīng)用程序,去掉垃圾回收機(jī)制可以提升他們的性能莉御。然而正如Popma強(qiáng)調(diào)的撇吞,如果要構(gòu)建一個可以使用Epsilon GC的庫,那將會“花費(fèi)大量的工程力量來確保應(yīng)用程序的內(nèi)存使用得當(dāng)不會溢出”礁叔。即便如此牍颈,也必須完成一場風(fēng)險評估來確定,選擇無操作GC的收益是否和實(shí)現(xiàn)無內(nèi)存垃圾的難度向匹配琅关。
然而我們很難預(yù)估怎樣的應(yīng)用程序可以被改寫成不會生產(chǎn)內(nèi)存垃圾的狀態(tài)煮岁。雖然這個話題復(fù)雜到難以在這樣一篇文章的篇幅內(nèi)講解清楚,但是下面列出的幾個想法會幫助你更好的思考這個問題:
- JVM中通過兩種機(jī)制來管理內(nèi)存:堆和棧涣易,這也是為什么會有兩種不同的內(nèi)存泄漏錯誤(OutOfMemoryError和StackOverflowError)画机。在棧上的內(nèi)存只對當(dāng)前線程可見,并且只存在于當(dāng)前執(zhí)行的方法之中新症。因此步氏,當(dāng)前的線程結(jié)束當(dāng)前的方法時,內(nèi)存會自動釋放并不需要調(diào)用GC徒爹。而在堆中的可以被整個應(yīng)用訪問荚醒,這意味著需要有一個獨(dú)立的內(nèi)存垃圾回收器來判斷是否有內(nèi)存已經(jīng)沒有被引用并且將它回收。
- 基本類型的內(nèi)存都會分配在棧上隆嗅,因此并不會造成GC方面的壓力界阁。如果在寫程序時大部分使用的都是基本類型,那么將只有少數(shù)對象需要垃圾回收器來對它們進(jìn)行管理胖喳。
- 不產(chǎn)生內(nèi)存垃圾和不產(chǎn)生對象是兩個概念泡躯;對象可以繼續(xù)被創(chuàng)建,但是并不需要垃圾回收器來對他們進(jìn)行監(jiān)控管理:
- 應(yīng)用程序或者庫可以在一開始就創(chuàng)建一些對象禀晓,并且一直重用他們精续。這種方式需要開發(fā)者對應(yīng)用程序使用內(nèi)存的每一步都了如指掌。
- 有時編譯器會識別出那些只在方法內(nèi)部調(diào)用的對象(參見 escape analysis)粹懒。當(dāng)確定某個對象不會出現(xiàn)在方法外部被引用時重付,它將會通過棧而不是堆的方式來給它分配內(nèi)存,因此會自動在當(dāng)前方法運(yùn)行結(jié)束后銷毀凫乖。
盡管這些方法都可行确垫,Pepperdine 卻指出它們共有的問題:上述方法會讓代碼寫起來非常不自然弓颈,且失去Java提供種種便利。同時删掀,Verburg也認(rèn)為Java的內(nèi)存管理機(jī)制就是它在業(yè)界如此受歡迎的主要原因翔冀。另外有一點(diǎn)我們必須知道,垃圾回收器雖然名字如此披泪,但它不只負(fù)責(zé)回收內(nèi)存垃圾纤子,內(nèi)存申請也是它的任務(wù)之一,對于Epsilon GC也不例外款票。據(jù)此控硼,Pepperdine認(rèn)為在沒有任何GC操作發(fā)生的情況下,Epsilon GC和普通的垃圾回收算法并沒有性能上的區(qū)別艾少,至少理論上如此卡乾。
盡管考慮到各種注意事項,Pepperdine和Verburg仍然確定Epsilon GC會對一小部分人非常游泳缚够,雖然Kirk表示這一小部分讀者甚至對無操作GC的實(shí)際用途保持懷疑幔妨。絕大部分的應(yīng)用程序需要在某些時刻回收內(nèi)存,因此需要存在一個有實(shí)際功能的垃圾回收器谍椅。
"合理的GC暫停時間對大部分應(yīng)用程序來說并不是什么問題误堡,所以我們?yōu)槭裁匆艞塉ava提供的種種便利來換取一個不確定的性能優(yōu)勢呢?“Kirk Pepperdine說到毯辅。
Pepperdine同樣也提醒我們埂伦,所有新增的功能都將加大OpenJDK的維護(hù)開銷,因此OpenJDK的開發(fā)者需要在添加新功能時有對應(yīng)的大局觀思恐。Oracle 已經(jīng)通過減少現(xiàn)存的垃圾回收器來減小維護(hù)成本沾谜,因此添加新的GC只會讓少部分用戶收益,并不一定是一種合理的資源投入胀莹。Shipil?v 似乎在起草JEP草案時就已經(jīng)考慮到這一點(diǎn)基跑,并初步分析認(rèn)為在這次新GC加入帶來的開銷將會盡可能的低。草案中相關(guān)數(shù)據(jù)已經(jīng)給出描焰。事實(shí)上Pepperdine和Verburg都認(rèn)為媳否,考慮到Shipil?v's豐富的經(jīng)驗(yàn),應(yīng)該對這次由他領(lǐng)導(dǎo)的倡議保持樂觀荆秦。
另一方面篱竭,Pepperdine強(qiáng)調(diào)說雖然OpenJDK是JVM的參考實(shí)現(xiàn),但它并沒有對垃圾回收器提出相應(yīng)的標(biāo)準(zhǔn)步绸。這意味著服務(wù)提供商完全可以自行實(shí)現(xiàn)和標(biāo)準(zhǔn)Java兼容的GC算法掺逼。這會導(dǎo)致分化出兩個不同意見的陣營:一方認(rèn)為實(shí)現(xiàn)在市場上穩(wěn)定運(yùn)行的算法應(yīng)該集成在商用版本的JVM中,另一方則會認(rèn)為這是OpenJDK上一個不錯的更新瓤介。
Remko還建議當(dāng)性能變得至關(guān)重要時吕喘,應(yīng)該考慮使用商業(yè)版JVM赘那,因?yàn)樵谫徺I許可證上的開銷會比自行研發(fā)并GC算法花費(fèi)的工程力量要小很多。Popma 和 Verburg還提到了另外一個正在開發(fā)中的 Shenandoah GC氯质,這項技術(shù)將專注于在超短時間來回收超大內(nèi)存的特性募舟。另外,專家們都認(rèn)為如果需要對應(yīng)用程序的性能有所要求闻察,仔細(xì)挑選一個合適的GC算法很可能會比不使用GC要好很多拱礁。
這個提案仍然十分“年輕”,在成為正式的JEP之前還需要繼續(xù)被審查和完善蜓陌。如果一切順利觅彰,Epsilon GC最終將會加入某個Java版本。雖然目前我們只能推測最終會添加到什么版本JVM中钮热,Martijn認(rèn)為有理由期待Epsilon GC將會加入到Java 10或者11。如果要說有什么好處的話烛芬,Epsilon GC至少能夠幫助理解GC的接口隧期,有助于成就一個更加模塊化的JVM。