北京軟件開(kāi)發(fā)公司log4j 2.6免垃圾收集,Java語(yǔ)言中流行的日志庫(kù)Log4j的較新版本Log4j 2.6,將引入一系列選項(xiàng)以運(yùn)行在免垃圾回收模式。該發(fā)布繼續(xù)跟隨前幾個(gè)發(fā)布版,嘗試提升日志庫(kù)的性能,并且已經(jīng)得到業(yè)界的積極響應(yīng)。據(jù)性能改進(jìn)倡議的引導(dǎo)者Remko Popm透露,下一步將會(huì)增加log4j可以運(yùn)行在免垃圾回收模式的場(chǎng)景數(shù)量。
2014年7月,log4j 2.0在日志框架領(lǐng)域革命性地引入了異步記錄器,相比于同步記錄器將吞吐率提升了6至68倍。這些結(jié)果可能令人影響深刻,但日志框架的性能損耗仍然占據(jù)了部分高吞吐率、低延時(shí)應(yīng)用響應(yīng)時(shí)間的很大一部分,這常常導(dǎo)致開(kāi)發(fā)者在部署時(shí)排除日志框架。對(duì)于高性能應(yīng)用程序進(jìn)行微調(diào)以避免垃圾回收導(dǎo)致的暫停能夠達(dá)到非常好的效果,log4j團(tuán)隊(duì)斷定這些性能提升能夠帶來(lái)更多的用戶。通過(guò)性能和Java專家Kirk Pepperdine的評(píng)論來(lái)判斷,該假設(shè)是成立的:
Java中的日志框架形勢(shì)不容樂(lè)觀。到今天為止,我很少碰到客戶反饋他們的系統(tǒng)沒(méi)有因?yàn)槿罩究蚣軐?dǎo)致的負(fù)面影響。我與到的一個(gè)極端例子是,一個(gè)客戶面臨4.5秒的時(shí)限,但是日志記錄占用了其中的4.2秒(很大一部分壓力來(lái)自于異步追加器)。我將對(duì)次版本發(fā)布非常感興趣。
防止垃圾回收是通過(guò)避免創(chuàng)建臨時(shí)對(duì)象來(lái)實(shí)現(xiàn)的,這意味著需要盡可能的復(fù)用已經(jīng)存在的對(duì)象。然而在較初發(fā)布的時(shí)候,整個(gè)庫(kù)沒(méi)有能夠做到免垃圾回收,因此開(kāi)發(fā)者如果希望實(shí)現(xiàn)該功能,需要注意追加器(appenders)、日志記錄器(loggers)、格式化布局(formatting layouts)和API使用時(shí)的限制。
應(yīng)用程序類型
部分被復(fù)用的對(duì)象保存在ThreadLocal區(qū)域中。這樣的設(shè)計(jì)對(duì)獨(dú)立的應(yīng)用程序來(lái)說(shuō)沒(méi)有問(wèn)題,但是對(duì)于web應(yīng)用可能會(huì)引起內(nèi)存泄漏。應(yīng)用服務(wù)器可能會(huì)將ThreadLocal保存在線程池中,這意味著即使應(yīng)用被卸載,用于日志記錄的對(duì)象仍然會(huì)保持引用。因此,通過(guò)ThreadLOcal來(lái)復(fù)用對(duì)象的功能在web應(yīng)用程序中默認(rèn)是關(guān)閉的,既log4j無(wú)法完全運(yùn)行在免垃圾回收模式。
日志記錄器
log4j防止觸發(fā)垃圾回收的另一個(gè)方式是在將文本轉(zhuǎn)換為字符數(shù)組的時(shí)候復(fù)用緩沖區(qū)。所有類型的應(yīng)用程序都可因此受益,且該功能默認(rèn)是開(kāi)啟的。然而使用同步日志記錄器的多線程應(yīng)用程序可能會(huì)有性能影響,因?yàn)椴煌木€程需要競(jìng)爭(zhēng)共享的緩沖區(qū)。如果遇到這種情況,應(yīng)該優(yōu)先使用異步日志記錄器,或者禁用共享緩沖區(qū)。
追加器
只有部分追加器已經(jīng)修改以避免創(chuàng)建臨時(shí)對(duì)象:Console(控制臺(tái))、File(文件)、RandomAccessFile(隨機(jī)訪問(wèn)文件)、上述追加器的回卷追加器、MemoryMappedFile(內(nèi)存映射文件)。任何其他追加器都會(huì)產(chǎn)生垃圾,并且需要被回收。然而需要注意的是,這些追加器本身可以免垃圾回收,仍然會(huì)有其他I/O相關(guān)的因素會(huì)影響它們的性能。
格式化布局
格式化布局可能是開(kāi)發(fā)者在試圖配置達(dá)到免垃圾回收時(shí)較棘手的部分,因?yàn)樗麄儾粌H需要關(guān)注所需使用的布局,還需要關(guān)注布局中的選項(xiàng)。GelfLayout(Graylog Extended Log Format)布局只有在壓縮選項(xiàng)禁用時(shí)才支持免垃圾回收,而PatternLayout只支持限定的轉(zhuǎn)換模式,任何其他轉(zhuǎn)換模式都會(huì)創(chuàng)建臨時(shí)對(duì)象。
API使用
API本身也已經(jīng)為避免創(chuàng)建臨時(shí)對(duì)象而修改。除了之前支持簡(jiǎn)單可變長(zhǎng)度參數(shù)(這樣會(huì)創(chuàng)建一個(gè)臨時(shí)數(shù)據(jù))的方法之外,log4j新增了所有方法的重載版本,較多支持10個(gè)參數(shù)。調(diào)用方法超過(guò)10個(gè)參數(shù)仍然會(huì)使用可變長(zhǎng)度參數(shù),這將會(huì)創(chuàng)建臨時(shí)數(shù)組。
這個(gè)限制對(duì)于通過(guò)SLF4J使用log4j的場(chǎng)景影響較大,因?yàn)檫@個(gè)門面庫(kù)只提供了較多兩個(gè)參數(shù)的非變長(zhǎng)參數(shù)。用戶如果希望使用超過(guò)兩個(gè)參數(shù),并運(yùn)行在免垃圾回收模式,就需要拋棄SLF4J。
對(duì)代碼的影響
雖然已經(jīng)做了向下兼容,以避免開(kāi)發(fā)者更新代碼,有一類臨時(shí)對(duì)象的創(chuàng)建和log4j框架本身無(wú)關(guān):對(duì)基本數(shù)據(jù)類型的自動(dòng)裝箱。為了確保JVM不將基本數(shù)據(jù)類型裝換成對(duì)應(yīng)的對(duì)象,開(kāi)發(fā)者在給log4j傳遞基本數(shù)據(jù)類型時(shí),可以使用靜態(tài)方法Unboxer.box()。該方法可以允許log4j直接處理基本數(shù)據(jù)類型而無(wú)需創(chuàng)建不必要的對(duì)象。
盡管有一系列的限制條件,這些改變已經(jīng)有潛力在嚴(yán)格性能需求的場(chǎng)景下顯著提升日志記錄的體驗(yàn)。那些因?yàn)楫?dāng)前限制無(wú)法使用免垃圾回收特性的開(kāi)發(fā)者,可以繼續(xù)關(guān)注變更列表,在未來(lái)的發(fā)布版本中可能會(huì)提供進(jìn)一步的改進(jìn)。