北(běi)京軟件(jiàn)開(kāi)發公司log4j 2.6免垃圾收集,Java語言中∏©™★流行(xíng)的(de)日(rì)志(zhì)庫Log4Ω¶✔j的(de)較新版本Log4j 2.6,将☆™引入一(yī)系列選項以運行(xíng)在免垃圾回收✔∏₹模式。該發布繼續跟随前幾個(gè)發布版,嘗試提升日(rì)志 ¥↑(zhì)庫的(de)性能(néng),并且已經得(♣↔de)到(dào)業(yè)界的(de)積極響應。據性能(néng)改進倡議÷ (yì)的(de)引導者Remko Popm透露,下(xià)一( <∞yī)步将會(huì)增加log4j可(kě)以運行(xíng)在→σ≈↕免垃圾回收模式的(de)場(chǎng)景數(sh→¶ù)量。
2014年(nián)7月(yuè),log4j 2.0在日(rì)σ&∞志(zhì)框架領域革命性地(dì)引入了δ≠∑(le)異步記錄器(qì),相(xiàng)比于同步記• ↔錄器(qì)将吞吐率提升了(le)6至68倍。這(zhè)些(x •iē)結果可(kě)能(néng)令人(rΩ<←én)影(yǐng)響深刻,但(dàn)日(rì)志(zhφβ↔¥ì)框架的(de)性能(néng)損耗仍然占λσ©據了(le)部分(fēn)高(gāo)吞吐率、低(dī)延時(sh•™✔í)應用(yòng)響應時(shí)間(jiān)的(de)很(hěn)大∞♦(dà)一(yī)部分(fēn),這(zhè)常常∑φ'導緻開(kāi)發者在部署時(shí)排除日(±"$♥rì)志(zhì)框架。對(duì)于高(gāo)性能(n≥←éng)應用(yòng)程序進行(xíng)微('™±wēi)調以避免垃圾回收導緻的(de)暫停能(néng)夠達到(dào)非常£¶♥♥好(hǎo)的(de)效果,log4j團隊斷定這(zhè)些(xiē)性能($ néng)提升能(néng)夠帶來(lá>$i)更多(duō)的(de)用(yòng)戶。通✔←(tōng)過性能(néng)和(hé)Jav>βa專家(jiā)Kirk Pepperdine的(de)評論 ₽來(lái)判斷,該假設是(shì)成立的(de):
Java中的(de)日(rì)志(zhì)框架形勢不(b ±₽ù)容樂(yuè)觀。到(dào)今天為(wèi)止,我很(h×'₩ěn)少(shǎo)碰到(dào)客戶反饋他(tā)們的(de)系統沒有(✔yǒu)因為(wèi)日(rì)志(zhì)$↔×★框架導緻的(de)負面影(yǐng)響。我與到(dà♥εo)的(de)一(yī)個(gè)極端例子(zǐ)是(sh Ω®φì),一(yī)個(gè)客戶面臨4.5∞∏↕秒(miǎo)的(de)時(shí)限,但(dàn)是(shì)日(rì)志(✘≠♠zhì)記錄占用(yòng)了(le)其中的(de)4.2秒(miǎoΩ&≠)(很(hěn)大(dà)一(yī)部分(fēn)壓力來(lái)自(zì☆✔)于異步追加器(qì))。我将對(duì)次版δ≤$本發布非常感興趣。
防止垃圾回收是(shì)通(tōng)過避免創建臨時(shí)♣×$對(duì)象來(lái)實現(xiàn)的(de),這(z £®hè)意味著(zhe)需要(yào)盡可(kě)能(néng)±✘δ的(de)複用(yòng)已經存在的(de)對(duì)象。然而在較初♥∑→®發布的(de)時(shí)候,整個(gè)庫沒有(yǒu)能(néng'♠☆ )夠做(zuò)到(dào)免垃圾回收,因此開(kāi)發者如(&>♣rú)果希望實現(xiàn)該功能(néng≈←),需要(yào)注意追加器(qì)(appenders₽₽)、日(rì)志(zhì)記錄器(qì)(log✘☆★gers)、格式化(huà)布局(for♥×↓matting layouts)和(hé)API使用(yòng)時(sδσ≥hí)的(de)限制(zhì)。
應用(yòng)程序類型
部分(fēn)被複用(yòng)的(de)對(du←©∑ì)象保存在ThreadLocal區(qū)域中。這(zhè)樣的(d≤>e)設計(jì)對(duì)獨立的(de)應₩§¥用(yòng)程序來(lái)說(shuō)沒有(yǒu)問(wèn)§₹→題,但(dàn)是(shì)對(duì)于web應用(yòng)可(kě)•★能(néng)會(huì)引起內(nèi)存洩漏。應用( ♠yòng)服務器(qì)可(kě)能(néng) €≈會(huì)将ThreadLocal保存在線程池中,這(zhè)意味著'λσ(zhe)即使應用(yòng)被卸載,用(yòng)γπ₽于日(rì)志(zhì)記錄的(de)對(duì)象仍然會(huì)保持引©∏$用(yòng)。因此,通(tōng)過T←±☆φhreadLOcal來(lái)複用(yòng)對(duì)象的(de)功能÷¶(néng)在web應用(yòng)程序中默認是(shì)關閉的(de)π✘<,既log4j無法完全運行(xíng)在免垃圾回收模式。
日(rì)志(zhì)記錄器(qì)
log4j防止觸發垃圾回收的(de)另一(yī)個(gè)方式是(shì≤&)在将文(wén)本轉換為(wèi)字符數(shù)組的(de)時(β✔'↓shí)候複用(yòng)緩沖區(qū)。所有(yǒ¥↔u)類型的(de)應用(yòng)程序都(dōu)可(kě)因此受益,且該功 ≤←能(néng)默認是(shì)開(kāi)啓的(de)。然而使用(yòng)♠γ✔同步日(rì)志(zhì)記錄器(qì)的(de)多≈☆(duō)線程應用(yòng)程序可(kě)能(néng)會(huì)有(y<"•ǒu)性能(néng)影(yǐng)響,因為(wèi)不(bù)同的(de)線>♦ λ程需要(yào)競争共享的(de)緩沖區(qū)。如(rú)果遇到ε(dào)這(zhè)種情況,應該優先使用(yòng)異步日(rì)志(zπ¶÷hì)記錄器(qì),或者禁用(yòng)共享≈ ☆€緩沖區(qū)。
追加器(qì)
隻有(yǒu)部分(fēn)追加器(qì)已經修改以'$±♠避免創建臨時(shí)對(duì)象:Cons♥ole(控制(zhì)台)、File(文(wé®∑ n)件(jiàn))、RandomAccessFile(随機(jī)訪問≥•(wèn)文(wén)件(jiàn))、上(shàng)述✘φ€σ追加器(qì)的(de)回卷追加器(qì)、MemoryMapped✘λFile(內(nèi)存映射文(wén)件($&↓$jiàn))。任何其他(tā)追加器(qì)都®←(dōu)會(huì)産生(shēng)÷↓÷垃圾,并且需要(yào)被回收。然而需要(yào)注意≠ ±的(de)是(shì),這(zhè)些(xiē)追加器(qì)本身(≈$±εshēn)可(kě)以免垃圾回收,仍然會(huì→ ♣£)有(yǒu)其他(tā)I/O相(xiàng)關的(de)$₹©☆因素會(huì)影(yǐng)響它們的(de)性能(néng)。
格式化(huà)布局
格式化(huà)布局可(kě)能(néng)是(₽∑÷£shì)開(kāi)發者在試圖配置達到(dào)免垃圾回✔×收時(shí)較棘手的(de)部分(fēn)↓¥±>,因為(wèi)他(tā)們不(bù)僅需要(yào)關注所需使用(yò ∞☆≠ng)的(de)布局,還(hái)需要(yào)關注布局中的(d↓↓®↑e)選項。GelfLayout(Graylog Ex↕tended Log Format)布局隻有(yǒu)在壓縮選©δ項禁用(yòng)時(shí)才支持免垃圾回收,而PaΩ"¥>tternLayout隻支持限定的(de)轉' 換模式,任何其他(tā)轉換模式都(dōu)會(huì)創建臨時(s₩hí)對(duì)象。
API使用(yòng)
API本身(shēn)也(yě)已經為(wèi)避免創建臨時(s Ω$hí)對(duì)象而修改。除了(le)之前支持簡單可(kěσπΩ)變長(cháng)度參數(shù)(這(zhè)樣會(huì)創建一×§(yī)個(gè)臨時(shí)數(shù)據)的(de)方↔↓法之外(wài),log4j新增了(le)所有(yǒu)方法的(de)重載¶ ✔£版本,較多(duō)支持10個(gè)參數(shù)。調用±♠♣ (yòng)方法超過10個(gè)參數(s✔♥ hù)仍然會(huì)使用(yòng)可(kě)變長(cháng)度參數(s×✔hù),這(zhè)将會(huì)創建臨時(shí)數(shù)組。
這(zhè)個(gè)限制(zhì)≥•€♥對(duì)于通(tōng)過SLF4J使用(yòng)log4•★j的(de)場(chǎng)景影(yǐng)響較大(dà),因為(w↕∞∞èi)這(zhè)個(gè)門(mén)面庫≈φ隻提供了(le)較多(duō)兩個(gè)參數(shù)的(de)✔$∑非變長(cháng)參數(shù)。用(yòng)戶如(rú)果希望使用€÷(yòng)超過兩個(gè)參數(shù),并運行(xíng)在免垃圾回收< λ模式,就(jiù)需要(yào)抛棄SLF4J。
對(duì)代碼的(de)影(yǐng)響
雖然已經做(zuò)了(le)向下(xià)兼容,↕<≈ 以避免開(kāi)發者更新代碼,有(yǒu)一(yī)>≥±σ類臨時(shí)對(duì)象的(de)創建和(hé®→γ)log4j框架本身(shēn)無關:對(duì)基本數(shù≤¶)據類型的(de)自(zì)動裝箱。為(wèi)了(le)₹>↓¶确保JVM不(bù)将基本數(shù)據類型裝✘≠φ換成對(duì)應的(de)對(duì)象,開(kāi)發者在給log•÷↑≠4j傳遞基本數(shù)據類型時(shí),可(kě®®)以使用(yòng)靜(jìng)态方法÷&<Unboxer.box()。該方法可(kě)以允許log4j直接處理(→←₹lǐ)基本數(shù)據類型而無需創建不(bù)必要(yào)的(α$♥φde)對(duì)象。
盡管有(yǒu)一(yī)系列的(de)限制¶>(zhì)條件(jiàn),這(zhè)些(xiē)改變已經有∏ (yǒu)潛力在嚴格性能(néng)需求的(de)場(chǎng β₩)景下(xià)顯著提升日(rì)志(z☆♦hì)記錄的(de)體(tǐ)驗。那(nà)些(xiē)因為(§₹←wèi)當前限制(zhì)無法使用(yòng)免垃圾回收特性的( ₽'$de)開(kāi)發者,可(kě)以繼續關注變更列表,在未來(lái)≈≈的(de)發布版本中可(kě)能(néng)會(huì)♠®♦π提供進一(yī)步的(de)改進。