1995年引入Java時(shí),它承諾自動(dòng)垃圾收集。通過將釋放對(duì)象的責(zé)任從開發(fā)人員轉(zhuǎn)移到Java虛擬機(jī)(JVM ),它徹底改變了內(nèi)存管理。整個(gè)行業(yè)都接受了這個(gè)創(chuàng)新的想法,因?yàn)殚_發(fā)人員不再需要擔(dān)心手動(dòng)內(nèi)存管理。從那時(shí)起,自動(dòng)垃圾收集就成了所有現(xiàn)代編程語言的默認(rèn)特性。
在這篇文章中,讓我們來探索垃圾收集過程中研究的一個(gè)關(guān)鍵性能指標(biāo):“GC吞吐量”。我們將理解它的含義,它在Java應(yīng)用程序中的重要性,以及它如何影響整體性能。此外,我們將深入研究提高GC吞吐量的可行策略,釋放其對(duì)現(xiàn)代軟件開發(fā)的益處。
什么是垃圾收集吞吐量?
每當(dāng)自動(dòng)垃圾收集事件運(yùn)行時(shí),它都會(huì)暫停應(yīng)用程序,以便從內(nèi)存中識(shí)別未引用的對(duì)象并將其驅(qū)逐出去。在暫停期間,不會(huì)處理任何客戶交易。垃圾收集吞吐量表示應(yīng)用程序處理客戶事務(wù)的時(shí)間百分比,以及垃圾收集活動(dòng)的時(shí)間百分比。例如,如果有人說他的應(yīng)用程序的GC吞吐量是98%,這意味著他的應(yīng)用程序用98%的時(shí)間處理客戶事務(wù),剩下的2%時(shí)間處理垃圾收集活動(dòng)。
高GC吞吐量是可取的,因?yàn)樗砻鲬?yīng)用程序正在有效地利用系統(tǒng)資源,從而最大限度地減少中斷并提高整體性能。相反,低GC吞吐量會(huì)導(dǎo)致垃圾收集暫停時(shí)間增加,影響應(yīng)用程序的響應(yīng)能力并導(dǎo)致性能瓶頸。監(jiān)控和優(yōu)化GC吞吐量對(duì)于確保應(yīng)用程序順利執(zhí)行和響應(yīng)至關(guān)重要。在下一節(jié)中,我們將探索找到應(yīng)用程序的GC吞吐量的方法,并了解如何解釋結(jié)果以優(yōu)化Java應(yīng)用程序的性能。讓我們開始吧!
如何找到應(yīng)用程序的GC吞吐量
垃圾收集日志是研究GC性能的最佳來源。如果你的應(yīng)用程序運(yùn)行在JVM中,你可以啟用GC日志記錄,繞過本文中提到的JVM參數(shù)。啟用GC日志記錄后,讓你的應(yīng)用程序處理流量至少一天,以觀察高流量和低流量時(shí)段。之后,你可以將生成的GC日志文件上傳到GC日志分析工具,以獲得有價(jià)值的見解。一些流行的GC日志分析工具有GCeasy、IBM GC & Memory Visualizer、HP Jmeter和Garbage Cat。這些工具將報(bào)告GC吞吐量以及其他重要的GC指標(biāo)。下面是GCeasy工具的摘錄,展示了各種GC關(guān)鍵性能指標(biāo)(KPI)的報(bào)告,包括GC吞吐量。
圖:GCeasy工具報(bào)告的GC吞吐量
垃圾收集吞吐量低的原因
垃圾收集吞吐量下降的原因可以分為三類:
性能問題
錯(cuò)誤的GC調(diào)優(yōu)
缺乏資源
讓我們?cè)谶@一部分詳細(xì)回顧一下這些類別。
a.性能問題
當(dāng)應(yīng)用程序出現(xiàn)性能問題時(shí),GC吞吐量會(huì)下降。下面是可能導(dǎo)致應(yīng)用程序性能下降的潛在性能原因。
1.內(nèi)存泄漏
圖:由于內(nèi)存泄漏,GC事件重復(fù)運(yùn)行
當(dāng)應(yīng)用程序遭受內(nèi)存泄漏時(shí),垃圾收集事件會(huì)重復(fù)運(yùn)行,而不會(huì)有效地回收內(nèi)存。在上圖中,你可以注意到右上角的紅色三角形簇,這表明GC事件在重復(fù)運(yùn)行。但是,內(nèi)存利用率沒有降低,這是內(nèi)存泄漏的典型跡象。在這種情況下,GC事件會(huì)消耗應(yīng)用程序的大部分時(shí)間,導(dǎo)致GC吞吐量和整體性能顯著下降。
2.連續(xù)GC暫停
圖:由于高流量,GC事件重復(fù)運(yùn)行
在一天中的高峰時(shí)段或運(yùn)行批處理時(shí),你的應(yīng)用程序可能會(huì)遇到高流量。因此,GC事件可能會(huì)連續(xù)運(yùn)行,以清理應(yīng)用程序創(chuàng)建的對(duì)象。上圖顯示了連續(xù)運(yùn)行的GC事件(注意上圖中的紅色箭頭)。這種情況會(huì)導(dǎo)致GC吞吐量在這段時(shí)間內(nèi)急劇下降。
3.重物產(chǎn)生率
低效的編程實(shí)踐會(huì)導(dǎo)致你的應(yīng)用程序創(chuàng)建大量不必要的對(duì)象。對(duì)象創(chuàng)建速率的增加迫使垃圾收集器非常頻繁地運(yùn)行,從而對(duì)GC吞吐量產(chǎn)生負(fù)面影響。為了解決這個(gè)問題,你可以使用HeapHero、YourKit或jProfiler等內(nèi)存分析器來分析你的應(yīng)用程序,以識(shí)別對(duì)象創(chuàng)建過多的區(qū)域,并相應(yīng)地優(yōu)化或減少對(duì)象的使用。
4.大而長(zhǎng)壽的物體
大而長(zhǎng)壽的對(duì)象對(duì)垃圾收集(GC)吞吐量和整體應(yīng)用程序性能有顯著的影響。這些對(duì)象消耗大量?jī)?nèi)存,并在堆中持續(xù)很長(zhǎng)時(shí)間,導(dǎo)致與GC相關(guān)的挑戰(zhàn)。要減輕這種影響,請(qǐng)考慮:
l 對(duì)象池:通過池化來重用對(duì)象,以最小化分配和GC。
l 最佳尺寸:創(chuàng)建適當(dāng)大小的對(duì)象以避免不必要的開銷。
l 弱引用:對(duì)可以積極收集的對(duì)象使用弱引用。
l 堆外存儲(chǔ):將堆外內(nèi)存用于大型或長(zhǎng)期數(shù)據(jù)。
b.錯(cuò)誤的GC調(diào)優(yōu)
應(yīng)用程序GC吞吐量下降的另一個(gè)重要原因是不正確的垃圾收集(GC)調(diào)優(yōu)。各種因素都可能導(dǎo)致這一問題。
5.錯(cuò)誤的GC算法選擇
截至2023年,OpenJDK平臺(tái)提供了一系列七種垃圾收集算法,包括串行、并行、CMS、G1 GC、ZGC、Shenandoah和Epsilon。選擇合適的GC算法至關(guān)重要,應(yīng)該基于應(yīng)用程序流量、模式、對(duì)象創(chuàng)建率和性能目標(biāo)等因素。選擇錯(cuò)誤的GC算法會(huì)大大降低應(yīng)用程序的GC吞吐量。
6.缺少(或不正確的)GC調(diào)優(yōu)
錯(cuò)誤地配置JVM參數(shù)或未能適當(dāng)?shù)卣{(diào)優(yōu)應(yīng)用程序也會(huì)導(dǎo)致GC吞吐量下降。正確的GC調(diào)優(yōu)對(duì)于將JVM的行為與應(yīng)用程序的需求保持一致至關(guān)重要。
7.錯(cuò)誤的代大小
JVM內(nèi)存分為內(nèi)部區(qū)域,包括年輕一代、老一代、元空間和本機(jī)內(nèi)存。這些區(qū)域大小的不正確配置會(huì)導(dǎo)致GC通量下降。
c.缺乏資源
系統(tǒng)和應(yīng)用程序級(jí)資源不足會(huì)導(dǎo)致應(yīng)用程序的垃圾收集(GC)吞吐量下降。
8.堆大小不足
分配不適當(dāng)?shù)亩汛笮?/span>(由-Xmx參數(shù)控制)和增加對(duì)象創(chuàng)建會(huì)導(dǎo)致更頻繁的GC事件。這種頻繁的GC活動(dòng)會(huì)導(dǎo)致GC吞吐量下降。要解決這個(gè)問題,請(qǐng)通過增加堆大小來滿足應(yīng)用程序的內(nèi)存需求,從而確保有一個(gè)大小合適的堆。
9.GC線程不足
垃圾收集線程的短缺會(huì)導(dǎo)致GC事件持續(xù)時(shí)間延長(zhǎng)。GC線程的數(shù)量由“ConcurrentGCThreads”和“ParallelGCThreads”JVM參數(shù)決定。分配足夠數(shù)量的GC線程對(duì)于提高GC吞吐量和最小化暫停是至關(guān)重要的。
10.系統(tǒng)資源不足
應(yīng)用程序中CPU周期不足或I/O活動(dòng)過多會(huì)顯著降低GC性能。確保服務(wù)器、虛擬機(jī)(VM)或承載應(yīng)用程序的容器上有足夠的CPU可用性至關(guān)重要。此外,最大限度地減少I/O活動(dòng)有助于保持最佳的GC吞吐量。
11.老版本的JDK
JDK開發(fā)團(tuán)隊(duì)持續(xù)改進(jìn)GC性能。在過時(shí)的JDK版本上運(yùn)行會(huì)妨礙你從最新的增強(qiáng)功能中獲益。為了最大限度地提高氣相色譜通量,建議保持JDK最新。
結(jié)論
在Java應(yīng)用程序開發(fā)領(lǐng)域,優(yōu)化垃圾收集(GC)吞吐量對(duì)于峰值性能至關(guān)重要。我們探討了GC通量的細(xì)微差別,從測(cè)量到影響因素。借助GCeasy、IBM GC和Memory Visualizer以及HP Jmeter等工具的洞察力,我們學(xué)會(huì)了識(shí)別和解決影響吞吐量的問題,無論是內(nèi)存泄漏還是不適當(dāng)?shù)恼{(diào)優(yōu)。隨著你繼續(xù)你的編碼之旅,希望這些策略能夠讓你釋放Java應(yīng)用程序的全部潛力,交付健壯、響應(yīng)迅速和高效的軟件體驗(yàn)。