使用正确的垃圾收集器将Java内存使用量降至最低
大小對(duì)于軟件至關(guān)重要。 很明顯,與大型整體方法相比,在微服務(wù)體系結(jié)構(gòu)中使用小型組件具有更多優(yōu)勢(shì)。 最新的Java版本的Jigsaw可幫助分解舊應(yīng)用程序或從頭開始構(gòu)建新的云原生應(yīng)用程序。
這種方法減少了磁盤空間,構(gòu)建時(shí)間和啟動(dòng)時(shí)間。 但是,它對(duì)RAM使用管理沒有足夠的幫助。 眾所周知,Java在許多情況下會(huì)消耗大量內(nèi)存。 同時(shí),許多人還沒有注意到Java在內(nèi)存使用方面已經(jīng)變得更加靈活,并且提供了滿足微服務(wù)需求的功能。 在本文中,我們將分享我們的經(jīng)驗(yàn),如何在Java進(jìn)程中調(diào)整RAM的使用以使其更具彈性,并獲得更快的擴(kuò)展和更低的總體擁有成本(TCO)的好處。
縮放有三個(gè)選項(xiàng):垂直,水平以及兩者的組合。 為了最大化結(jié)果,首先您需要以最佳方式設(shè)置垂直縮放。 然后,當(dāng)您的項(xiàng)目水平增長時(shí),單個(gè)容器內(nèi)的預(yù)配置資源消耗將被復(fù)制到每個(gè)實(shí)例,效率將成比例地增長。
如果配置正確,則垂直縮放可完美適用于微服務(wù)和整體,可根據(jù)容器內(nèi)的當(dāng)前負(fù)載優(yōu)化內(nèi)存和CPU使用率。 選定的垃圾收集器是主要的基礎(chǔ)磚之一,其設(shè)置會(huì)影響整個(gè)項(xiàng)目。
OpenJDK有五種廣泛使用的垃圾收集器解決方案:
- G1
- 平行
- ConcMarkSweep(CMS)
- 序列號(hào)
- 雪蘭多
讓我們看看它們?cè)诳s放方面的表現(xiàn)以及可以應(yīng)用哪些設(shè)置來改善結(jié)果。
為了進(jìn)行測(cè)試,我們將使用一個(gè)示例Java應(yīng)用程序來幫助跟蹤JVM垂直縮放結(jié)果: https : //github.com/jelastic/java-vertical-scaling-test
將為每個(gè)GC測(cè)試啟動(dòng)以下JVM啟動(dòng)選項(xiàng):
java -XX:+Use[gc_name]GC -Xmx2g -Xms32m -jar app.jar [sleep]哪里:
- [gc_name]將替換為特定的垃圾收集器類型
- Xms是擴(kuò)展步驟(本例中為32 MB)
- Xmx是最大縮放限制(本例中為2 GB)
- [sleep]是內(nèi)存加載周期之間的間隔(以毫秒為單位),默認(rèn)為10
目前,為了完全釋放未使用的資源,需要調(diào)用Full GC。 它可以通過各種選項(xiàng)輕松啟動(dòng):
- jcmd <pid> GC.run –執(zhí)行外部調(diào)用
- System.gc() – 源代碼內(nèi)
- jvisualvm –通過出色的VisualVM故障排除工具手動(dòng)進(jìn)行
- -javaagent:agent.jar –可插入的常用方法。 Github repo Java Memory Agent上提供了開源自動(dòng)化附件。
可以在輸出日志中跟蹤內(nèi)存使用情況,或使用VisualVM進(jìn)行更深入的查看。
G1垃圾收集器
對(duì)于Java生態(tài)系統(tǒng)來說,好消息是,從JDK 9開始,默認(rèn)情況下啟用了現(xiàn)代收縮的G1垃圾收集器。 如果使用較低版本的JDK,則可以使用-XX:+UseG1GC參數(shù)啟用G1。
G1的主要優(yōu)勢(shì)之一是能夠壓縮可用的內(nèi)存空間,而無需花費(fèi)較長的暫停時(shí)間和不提交未使用的堆的能力。 我們發(fā)現(xiàn),對(duì)于在OpenJDK或HotSpot JDK上運(yùn)行的Java應(yīng)用程序進(jìn)行垂直擴(kuò)展,此GC是最佳選擇。
為了更好地了解JVM在不同的內(nèi)存壓力級(jí)別下的行為,我們將運(yùn)行以下三種情況:1)快速,2)中速和3)內(nèi)存使用量增長緩慢。 這樣,我們可以檢查G1人機(jī)工程學(xué)的智能程度以及GC如何處理不同的內(nèi)存使用動(dòng)態(tài)。
內(nèi)存使用量快速增長
java -XX:+UseG1GC -Xmx2g -Xms32m -jar app.jar 0內(nèi)存在25秒內(nèi)從32 MiB增長到1 GiB。
G1內(nèi)存使用量快速增長
如果內(nèi)存使用量增長非常快,則根據(jù)其內(nèi)部自適應(yīng)優(yōu)化算法,JVM人體工程學(xué)將忽略Xms擴(kuò)展步驟,并更快地保留RAM。 結(jié)果,相對(duì)于實(shí)際使用量的快速增長(藍(lán)色),我們看到了JVM(橙色)的RAM分配要快得多。 因此,即使出現(xiàn)負(fù)載峰值,使用G1還是安全的。
中等內(nèi)存使用量增長
java -XX:+UseG1GC -Xmx2g -Xms32m -jar app.jar 10在4個(gè)周期內(nèi),內(nèi)存在90秒內(nèi)從32 MiB增長到1 GiB。
有時(shí),要使JVM符合人體工程學(xué),需要幾個(gè)周期才能找到最佳的RAM分配算法。
G1中型內(nèi)存使用量增長
如我們所見,JVM在第4 個(gè)周期中對(duì)人體工程學(xué)進(jìn)行了調(diào)整,以使垂直擴(kuò)展在可重復(fù)的周期中非常有效
內(nèi)存使用量增長緩慢
java -XX:+UseG1GC -Xmx2g -Xms32m -jar app.jar 100內(nèi)存從32 MiB增長到1 GiB,增量時(shí)間增長了大約300秒。 非常靈活和高效的資源擴(kuò)展符合我們的期望-令人印象深刻。
G1內(nèi)存使用量增長緩慢
如您所見,橙色區(qū)域(保留的RAM)隨著藍(lán)色區(qū)域(實(shí)際使用)的增長而緩慢增加。 因此,沒有過量使用或不必要保留的內(nèi)存。
重要提示:激進(jìn)堆或垂直縮放
用于提高Java應(yīng)用程序性能的流行JVM配置通常會(huì)阻礙有效地垂直擴(kuò)展的能力。 因此,您需要在優(yōu)先級(jí)之間進(jìn)行選擇,這些優(yōu)先級(jí)對(duì)于您的應(yīng)用程序最重要。
廣泛使用的設(shè)置之一是激活積極堆,以最大程度地利用堆的物理內(nèi)存。 讓我們分析一下使用此配置時(shí)發(fā)生的情況。
java -XX:+UseG1GC -Xmx2g -Xms2g要么
java -XX:+UseG1GC -Xmx2g -XX:+AggressiveHeapG1激進(jìn)堆
如我們所見,保留堆(橙色)是恒定的,并且不會(huì)隨時(shí)間變化,因此容器中沒有JVM的垂直縮放。 即使您的應(yīng)用程序僅使用可用RAM的一小部分(藍(lán)色),其余部分也無法與其他進(jìn)程或其他容器共享,因?yàn)樗淹耆峙浣oJVM。
因此,如果要垂直擴(kuò)展應(yīng)用程序,請(qǐng)確保未啟用主動(dòng)堆(參數(shù)應(yīng)為-XX:-AggressiveHeap ),也不-XX:-AggressiveHeap -Xms定義為與-Xmx一樣高(例如,不要聲明-Xmx2g -Xms2g ) 。
并行垃圾收集器
并行是高吞吐量GC,默認(rèn)情況下在JDK8中使用。 同時(shí),它不適合內(nèi)存縮減,因此不適合進(jìn)行靈活的垂直縮放。 為了確認(rèn)這一點(diǎn),讓我們對(duì)示例應(yīng)用程序進(jìn)行測(cè)試:
java -XX:+UseParallelGC -Xmx2g -Xms32m -jar app.jar 10平行垃圾收集器
如我們所見,未使用的RAM不會(huì)釋放回OS。 帶有并行GC的JVM可以永久保留它,甚至不考慮顯式的Full GC調(diào)用。
因此,如果您希望根據(jù)應(yīng)用程序負(fù)載從垂直縮放中受益,請(qǐng)將Parallel更改為JDK中可用的收縮GC。 它將所有活動(dòng)對(duì)象打包在一起,刪除垃圾對(duì)象,并取消提交未使用的內(nèi)存并將其釋放回操作系統(tǒng)。
串行和ConcMarkSweep垃圾收集器
Serial和ConcMarkSweep也在縮小垃圾收集器,并且可以垂直擴(kuò)展JVM中的內(nèi)存使用量。 但是與G1相比,它們需要4個(gè)完整的GC周期才能釋放所有未使用的資源。
讓我們看看這兩個(gè)垃圾收集器的測(cè)試結(jié)果:
java -XX:+UseSerialGC -Xmx2g -Xms32m -jar app.jar 10串行垃圾收集器
java -XX:+UseConcMarkSweepGC -Xmx2g -Xms32m -jar app.jar 10ConcMarkSweep垃圾收集器
從JDK9開始,可以使用新的JVM選項(xiàng)-XX:-ShrinkHeapInSteps加快內(nèi)存釋放速度,該選項(xiàng)在第一個(gè)完整GC周期后立即減少已提交的RAM。
雪蘭多亞垃圾收集器
Shenandoah是垃圾收集器中的一顆冉冉升起的新星,該垃圾收集器已經(jīng)被視為即將推出的JVM垂直擴(kuò)展最佳解決方案。
與其他服務(wù)器相比,主要的不同是能夠異步收縮(取消提交未使用的RAM并將其釋放給OS),而無需調(diào)用Full GC。 Shenandoah可以在檢測(cè)到可用內(nèi)存后立即壓縮活動(dòng)對(duì)象,清理垃圾并將RAM釋放回OS。 省略Full GC的可能性可以消除相關(guān)的性能下降。
讓我們看看它在實(shí)踐中如何工作:
java -XX:+UseShenandoahGC -Xmx2g -Xms32m -XX:+UnlockExperimentalVMOptions -XX:ShenandoahUncommitDelay=1000 -XX:ShenandoahGuaranteedGCInterval=10000 -jar app.jar 10在這里,我們添加了雪南多厄可用的一些額外參數(shù):
- -XX:+UnlockExperimentalVMOptions –啟用下面列出的uncommit選項(xiàng)所需
- -XX:ShenandoahUncommitDelay=1000 –垃圾收集器將開始取消提交超過此時(shí)間(以毫秒為單位)的未使用內(nèi)存。 請(qǐng)注意,當(dāng)應(yīng)用程序想要取回內(nèi)存時(shí),將延遲設(shè)置得太低可能會(huì)導(dǎo)致分配停頓。 在實(shí)際部署中,建議使延遲大于1秒
- -XX:ShenandoahGuaranteedGCInterval=10000 -這樣可以保證在指定的時(shí)間間隔(以毫秒為單位)內(nèi)的GC周期
雪蘭多亞垃圾收集器
雪蘭多厄非常靈活,只分配必要的資源。 它還壓縮了用過的RAM(藍(lán)色),并即時(shí)將未消耗的保留RAM(橙色)釋放回操作系統(tǒng),而無需進(jìn)行昂貴的Full GC調(diào)用。 請(qǐng)注意,此GC是實(shí)驗(yàn)性的,因此您對(duì)穩(wěn)定性的反饋將對(duì)其創(chuàng)建者有所幫助。
結(jié)論
Java會(huì)不斷完善和適應(yīng)不斷變化的需求。 因此,目前,對(duì)于微服務(wù)和傳統(tǒng)應(yīng)用程序的云托管而言,RAM的需求不再是問題,因?yàn)橐呀?jīng)有了正確地對(duì)其進(jìn)行擴(kuò)展,清理垃圾并釋放所需過程資源的正確工具和方法。 通過智能配置,Java對(duì)于所有項(xiàng)目范圍(從云原生啟動(dòng)到傳統(tǒng)企業(yè)應(yīng)用程序)都可以具有成本效益。
翻譯自: https://www.javacodegeeks.com/2017/11/minimize-java-memory-usage-right-garbage-collector.html
總結(jié)
以上是生活随笔為你收集整理的使用正确的垃圾收集器将Java内存使用量降至最低的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 双子女跟什么星座最配对(与双子女最搭最配
- 下一篇: Java命令行界面(第30部分):观察