Log4j 2:性能接近疯狂
最近,Apache社區(qū)中一位受人尊敬的成員嘗試了Log4j 2并在Twitter上寫(xiě)道:
@TheASF #log4j2搖搖欲墜 ! 性能接近瘋狂^^ http://t.co/04K6F4Xkaa
— Mark Struberg(@struberg) 2013年5月7日
 (來(lái)自Mark Struberg的名言:@TheASF#log4j2搖搖欲墜!性能接近瘋狂^^ http://logging.apache.org/log4j/2.x/) 
 
在Remko Popma貢獻(xiàn)了一些東西(現(xiàn)在稱(chēng)為“ AsyncLoggers”)之后不久便發(fā)生了。 某些人可能知道Log4j 2已經(jīng)具有AsyncAppenders。 它們相似,就像您在Log4j 1和其他日志記錄框架中可以找到的一樣。
老實(shí)說(shuō):我對(duì)新功能并不感到興奮,直到我閱讀了有關(guān)其性能的推文并對(duì)此感到好奇。 顯然,Java日志記錄有許多目標(biāo)。 其中: 日志記錄必須和地獄一樣快 。 沒(méi)有人希望他的日志記錄框架成為瓶頸。 當(dāng)然,登錄時(shí)總會(huì)有成本。 CPU必須執(zhí)行一些操作。 即使您決定不編寫(xiě)日志語(yǔ)句,也正在發(fā)生某些事情。 預(yù)計(jì)日志是不可見(jiàn)的。
 到目前為止,眾所周知的日志記錄框架在速度上是相似的。 基準(zhǔn)畢竟是不可靠的。 我們已經(jīng)在Apache Logging上建立了一些基準(zhǔn)。 有時(shí),一個(gè)日志記錄框架會(huì)獲勝,有時(shí)則是另一個(gè)。 但總而言之,您可以說(shuō)他們都很好 
 您可以選擇自己喜歡的任何方式。 直到獲得Remko的貢獻(xiàn),Log4j 2變得“異常快速”。 
運(yùn)行一個(gè)線(xiàn)程的小型軟件項(xiàng)目可能不太在乎性能。 在運(yùn)行SaaS時(shí),您根本不知道您的應(yīng)用何時(shí)會(huì)吸引到您需要擴(kuò)展的吸引力。 然后,您突然需要一些額外的電源。
使用Log4j 2,運(yùn)行64個(gè)線(xiàn)程可能為您帶來(lái)的日志吞吐量是同類(lèi)框架的十二倍。
我們說(shuō)每秒超過(guò)18,000,000條消息,而其他消息在同一環(huán)境中的發(fā)送量大約為1,500,000條或更少 。
我看到了圖表,但簡(jiǎn)直不敢相信。 一定有問(wèn)題。 我重新檢查了。 我自己進(jìn)行了測(cè)試。 就像這樣: Log4j 2的速度非常快。
異步性能,最后閱讀時(shí)間:2013年7月19日
截至目前,我們擁有一個(gè)日志記錄框架,該框架的性能比那里的其他所有日志記錄框架都要好。 到目前為止,如果速度很重要,那么當(dāng)我們不想使用Log4j 2時(shí),我們需要證明我們的決定是正確的。 Log4j 2之外的所有其他內(nèi)容都可能成為瓶頸和風(fēng)險(xiǎn)。 有了如此快速的日志記錄框架,您甚至可以考慮比以前更多地記錄生產(chǎn)中的日志。
最終,我給雷姆科寫(xiě)了一封電子郵件,問(wèn)他舊的AsyncAppenders和新的異步記錄器之間到底有什么區(qū)別 。
舊的AsynAppenders和新的AsyncLoggers之間的區(qū)別
他告訴我:“異步記錄器在做兩件事上與AsyncAppender有所不同,”他們?cè)噲D在將日志消息傳遞到另一個(gè)線(xiàn)程之前做最少的工作,并且他們使用不同的機(jī)制在生產(chǎn)者和生產(chǎn)者之間傳遞信息。消費(fèi)者線(xiàn)程。 AsyncAppender使用ArrayBlockingQueue將消息傳遞給寫(xiě)入磁盤(pán)的線(xiàn)程, 異步記錄器使用LMAX Disruptor庫(kù) 。 特別是Disruptor的性能差異很大。”
換句話(huà)說(shuō),AsyncAppender使用先進(jìn)先出隊(duì)列來(lái)處理消息。 但是異步記錄器使用了新的東西-Disruptor。 老實(shí)說(shuō),我從未聽(tīng)說(shuō)過(guò)。 而且,我從未想過(guò)要擴(kuò)展我的日志記錄框架。 當(dāng)有人說(shuō)“擴(kuò)展系統(tǒng)”時(shí),我想到了數(shù)據(jù)庫(kù),應(yīng)用服務(wù)器等等,但通常不會(huì)記錄日志。 在生產(chǎn)中,記錄已關(guān)閉。 故事結(jié)局。
但是,雷姆科(Remko)考慮進(jìn)行日志記錄時(shí)進(jìn)行擴(kuò)展。
“查看異步記錄器的性能測(cè)試結(jié)果,您會(huì)注意到的第一件事是,某些記錄方式的伸縮性要好于其他方式。 通過(guò)更好地?cái)U(kuò)展,我的意思是當(dāng)添加更多線(xiàn)程時(shí),您將獲得更多的吞吐量。 如果您添加的每個(gè)線(xiàn)程的吞吐量都增加了一個(gè)恒定值,那么您將具有線(xiàn)性可伸縮性。 這是非常可取的,但可能很難實(shí)現(xiàn)。”他寫(xiě)道。
“將同步與異步進(jìn)行比較,您將期望任何異步機(jī)制的擴(kuò)展都比同步日志記錄好得多,因?yàn)槟辉僭谏a(chǎn)線(xiàn)程中執(zhí)行I / O,而且我們都知道'I / O很慢'(而且我會(huì)再說(shuō)一遍)”。
是的,完全是我的理解。 我認(rèn)為將某些內(nèi)容發(fā)送到隊(duì)列就足夠了,而其他的則可以將其接收并編寫(xiě)消息。 該應(yīng)用程序?qū)⒗^續(xù)運(yùn)行。 雷姆科寫(xiě)道,這正是舊的AsyncAppender所做的:
“使用AsyncAppender,您的所有應(yīng)用程序線(xiàn)程所需要做的就是創(chuàng)建一個(gè)LogEvent對(duì)象,并將其放在ArrayBlockingQueue上; 然后,使用線(xiàn)程將這些事件從隊(duì)列中移出并完成所有耗時(shí)的工作。 即,將事件轉(zhuǎn)換為字節(jié)并將這些字節(jié)寫(xiě)入I / O設(shè)備的工作。 由于應(yīng)用程序線(xiàn)程不需要執(zhí)行I / O,因此您希望它可以更好地?cái)U(kuò)展,這意味著添加線(xiàn)程將允許您記錄更多事件。
如果您相信像我一樣,請(qǐng)坐下并深呼吸。 我們錯(cuò)了。
他寫(xiě)道:“事實(shí)可能并非如此。”
“如果查看所有日志記錄框架的AsyncAppenders的性能數(shù)字,就會(huì)發(fā)現(xiàn),每增加一倍的線(xiàn)程數(shù),每個(gè)線(xiàn)程的吞吐量就會(huì)減少一半。”
“因此,您的總吞吐量或多或少保持不變! 他告訴我,AsyncAppenders比同步日志記錄要快,但是它們?cè)谀撤N意義上是相似的,即當(dāng)您添加更多線(xiàn)程時(shí),它們都不為您提供更多的總吞吐量。
它像錘子一樣打在我身上。 基本上,而不是通過(guò)添加更多線(xiàn)程來(lái)提高日志記錄速度,基本上是:沒(méi)有。 畢竟,直到現(xiàn)在Appender都沒(méi)有擴(kuò)展。 我問(wèn)雷姆科為什么會(huì)這樣。
事實(shí)證明,隊(duì)列并不是在線(xiàn)程之間傳遞信息的最佳數(shù)據(jù)結(jié)構(gòu)。 作為標(biāo)準(zhǔn)Java庫(kù)的一部分的并發(fā)隊(duì)列使用鎖來(lái)確保值不會(huì)被破壞并確保線(xiàn)程之間的數(shù)據(jù)可見(jiàn)性。
LMAX破壞者?
“ LMAX團(tuán)隊(duì)對(duì)此進(jìn)行了大量研究,發(fā)現(xiàn)這些隊(duì)列有很多鎖爭(zhēng)用。 他們發(fā)現(xiàn)一個(gè)有趣的事情是隊(duì)列始終是滿(mǎn)的或空的:如果生產(chǎn)者速度更快,則在大多數(shù)情況下您的隊(duì)列將是滿(mǎn)的(這本身可能就是一個(gè)問(wèn)題)。 如果您的使用者速度足夠快,則您的隊(duì)列在大多數(shù)情況下將是空的。 無(wú)論哪種方式,您都將在隊(duì)列的開(kāi)頭或結(jié)尾都有爭(zhēng)用,生產(chǎn)者線(xiàn)程和使用者線(xiàn)程都想在其中更新同一字段。 為了解決這個(gè)問(wèn)題,LMAX團(tuán)隊(duì)提出了Disruptor庫(kù),該庫(kù)是用于在線(xiàn)程之間傳遞消息的無(wú)鎖數(shù)據(jù)結(jié)構(gòu)。 這是Disruptor和ArrayBlockingQueue之間的性能比較 : 性能比較 。”
哇。 經(jīng)過(guò)這些年的Java編程,我實(shí)際上再次感覺(jué)像是初級(jí)程序員。 我錯(cuò)過(guò)了LMAX破壞者,甚至從未考慮使用Queue帶來(lái)的性能問(wèn)題。 我想知道到目前為止還沒(méi)有發(fā)現(xiàn)什么其他性能問(wèn)題。 我意識(shí)到,我不得不重新學(xué)習(xí)Java。
我問(wèn)雷姆科,他怎么能找到像LMAX破壞者這樣的圖書(shū)館。 我的意思是,沒(méi)有人編寫(xiě)軟件,創(chuàng)建隊(duì)列類(lèi)的實(shí)例,懷疑其性能并最終在互聯(lián)網(wǎng)上搜索“更好的東西”。
還是真的有這種人?
“我如何發(fā)現(xiàn)Disruptor? 簡(jiǎn)短的答案是,這全都是錯(cuò)誤。”他開(kāi)始說(shuō)道。
“好吧,也許這有點(diǎn)太短了,所以答案更長(zhǎng)一些:我的一位同事寫(xiě)了一個(gè)小的記錄器,本質(zhì)上在隊(duì)列中添加了帶時(shí)間戳的日志消息,并帶有后臺(tái)線(xiàn)程,這些線(xiàn)程使這些字符串脫離了隊(duì)列。并將它們寫(xiě)入磁盤(pán)。 他之所以這樣做,是因?yàn)樗枰萳og4j-1.x更好的性能。 我做了一些測(cè)試,發(fā)現(xiàn)它更快,我不記得確切多少。 我很驚訝,因?yàn)槲乙呀?jīng)使用log4j多年了,并且從未想到過(guò)它會(huì)輕易勝過(guò)。 在那之前,我一直以為著名的庫(kù)會(huì)很快,因?yàn)椤f(shuō)實(shí)話(huà),我只是以為。 因此,這讓我大開(kāi)眼界。 但是,自定義記錄器在功能上有些勉強(qiáng),所以我開(kāi)始四處尋找替代方案。”
“在我開(kāi)始談?wù)揇isruptor之前,我必須坦白一些東西。 最近,我回過(guò)頭來(lái)查看自定義記錄器比log4j-1.x快多少,但是當(dāng)我測(cè)量時(shí),它實(shí)際上要慢一些! 原來(lái),我一直在將自定義記錄器與log4j-2.0的舊beta(我認(rèn)為beta3或beta4)進(jìn)行比較。 這些Beta版中的AsyncAppender仍然存在性能問(wèn)題(如果您好奇,則為L(zhǎng)OG4J2-153)。 如果我將自定義記錄器與log4j-1.x中的AsyncAppender進(jìn)行了比較,我會(huì)發(fā)現(xiàn)log4j-1.x更快,并且我不會(huì)再考慮了。 但是由于犯了這個(gè)錯(cuò)誤,我開(kāi)始尋找功能更豐富的其他高性能日志記錄庫(kù)。 我沒(méi)有找到這樣的日志庫(kù),但是遇到了很多其他有趣的東西,包括Disruptor。 最終,我決定嘗試將具有良好代碼基礎(chǔ)的Log4j-2與Disruptor結(jié)合使用。 結(jié)果最終被Log4j-2本身接受,其余的,正如他們所說(shuō)的,已成為歷史。”
“我在這里提到的一件事是彼得·勞瑞(Peter Lawrey)的編年史圖書(shū)館 。 Chronicle使用內(nèi)存映射文件以極低的延遲每秒將數(shù)千萬(wàn)條消息寫(xiě)入磁盤(pán)。 還記得上面我說(shuō)過(guò)的“我們都知道I / O速度很慢”嗎? 紀(jì)事表明,同步I / O可以非常非常快。 ”。
“通過(guò)彼得的工作,我遇到了破壞者。 關(guān)于Disruptor的資料很多。 只是給您一些提示:
- 馬丁·福勒(Martin Fowler):LMAX
- 特里莎(Trisha Lee)在引擎蓋下的LMAX上使用 (現(xiàn)在略過(guò)時(shí),但我知道的最詳細(xì)的資料)
- …像這樣的視頻演示
強(qiáng)烈建議使用Disruptor Google組。
推薦的有關(guān)Java性能的閱讀材料通常是:
- 馬丁·湯普森(Martin Thompson)的“機(jī)械同情”
- 馬丁·湯普森演講。
Martin Thompson就Java高性能計(jì)算的各個(gè)方面做了很多文章和演示。 他出色地完成了引擎蓋下正在進(jìn)行的復(fù)雜操作。”
閱讀此電子郵件后,我的書(shū)簽文件夾已滿(mǎn),并且我非常感謝您有很多起點(diǎn)來(lái)提高我對(duì)Java性能的了解。
我應(yīng)該默認(rèn)使用AsyncLoggers嗎?
我確定我想使用新的異步記錄器。 這聽(tīng)起來(lái)真是太棒了。 但另一方面,我有點(diǎn)害怕,甚至有點(diǎn)偏執(zhí),無(wú)法包括新的依賴(lài)項(xiàng)或新技術(shù),例如新的Log4j 2 Async Loggers。 我問(wèn)雷姆科,他是否默認(rèn)使用新功能,還是僅在少數(shù)有限的用例中啟用它們。
“ 我默認(rèn)使用異步記錄器 ,是的。”他寫(xiě)道。 “一個(gè)用例的時(shí)候,你會(huì)_not_要使用異步日志記錄是當(dāng)您使用日志記錄審計(jì)目的。 在這種情況下,記錄錯(cuò)誤是您的應(yīng)用程序需要了解和處理的問(wèn)題。 我相信大多數(shù)應(yīng)用程序都是不同的,因?yàn)樗鼈儾惶诤跤涗涘e(cuò)誤。 大多數(shù)應(yīng)用程序都不想在發(fā)生日志記錄異常時(shí)停止,實(shí)際上,他們甚至都不希望知道它。 默認(rèn)情況下,Log4j-2.0中的追加器將抑制異常,因此應(yīng)用程序無(wú)需嘗試/捕獲每個(gè)日志語(yǔ)句。 如果這是您的用法,那么使用異步記錄器將不會(huì)造成任何損失,因此您只能獲得收益,即性能得到改善。”
“我應(yīng)該提到的一個(gè)不錯(cuò)的小細(xì)節(jié)是,異步記錄器和異步附加器都修復(fù)了一些在Log4j-1.x中一直困擾我的東西,即它們將在記錄隊(duì)列中的最后一個(gè)事件后刷新緩沖區(qū) 。 對(duì)于Log4j-1.x,如果使用緩沖的I / O,則通常看不到最后幾個(gè)日志事件,因?yàn)樗鼈內(nèi)钥ㄔ趦?nèi)存緩沖區(qū)中。 唯一的選擇是將InstantFlush設(shè)置為true,這將在每個(gè)單個(gè)日志事件上強(qiáng)制使用磁盤(pán)I / O,并會(huì)影響性能。 使用Log4j-2.0中的Async Loggers和Appenders,您的日志語(yǔ)句都被刷新到磁盤(pán)上,因此它們始終可見(jiàn),但這是以非常有效的方式發(fā)生的。”
登錄使用Log4js AsyncLoggers冒險(xiǎn)嗎?
但是考慮到Log4j-1存在嚴(yán)重的線(xiàn)程問(wèn)題,并且現(xiàn)代世界一直在使用云計(jì)算和集群來(lái)擴(kuò)展其應(yīng)用程序, 異步日志記錄不是某種額外的風(fēng)險(xiǎn)嗎? 還是安全? 我知道我的問(wèn)題聽(tīng)起來(lái)像是決策者而不是開(kāi)發(fā)人員的問(wèn)題。 但是整個(gè)LMAX對(duì)我來(lái)說(shuō)還是那么新,并且由于我保留了舊的而且非常丑陋的Log4j 1代碼,所以我只需要問(wèn)一下。
雷姆科:“那里有很多問(wèn)題。 首先,從并發(fā)角度看,Log4j-2是否比Log4j-1.x安全? 我相信是這樣。 Log4j-2團(tuán)隊(duì)付出了巨大的努力來(lái)支持多線(xiàn)程應(yīng)用程序,并且異步記錄器只是該項(xiàng)目的一個(gè)非常新的且相對(duì)較小的功能。 與Log4j-1.x相比,Log4j-2使用的粒度鎖定更多,并且在結(jié)構(gòu)上更簡(jiǎn)單,這將導(dǎo)致更少的問(wèn)題,并且出現(xiàn)的任何問(wèn)題都將更易于解決。”
“另一方面,Log4j-2仍處于測(cè)試階段,并且仍在積極開(kāi)發(fā)中,盡管最近我認(rèn)為大多數(shù)精力都花在了修復(fù)問(wèn)題和捆綁松散的末端上,而不是添加新功能。 我相信它足夠穩(wěn)定以供生產(chǎn)使用。 如果出于性能或其他原因考慮使用Log4j-2,我建議您進(jìn)行盡職調(diào)查和測(cè)試,就像在項(xiàng)目中采用任何其他第三方庫(kù)之前一樣。”
(旁注:可以很快找到Log4j2的穩(wěn)定版本,很可能是2013年秋天)。
對(duì)我來(lái)說(shuō)聽(tīng)起來(lái)不錯(cuò)。 是的,盡管我個(gè)人沒(méi)有在Log4j 2存儲(chǔ)庫(kù)中編寫(xiě)代碼,但從我對(duì)項(xiàng)目的觀察中我可以完全同意這一點(diǎn)。
“我看到的另一個(gè)問(wèn)題是: 異步日志記錄比同步日志記錄有風(fēng)險(xiǎn)嗎? 我不這么認(rèn)為,實(shí)際上,如果您的應(yīng)用程序是多線(xiàn)程的,則情況可能恰恰相反:一旦將日志事件移交給執(zhí)行I / O的使用者線(xiàn)程,則只有一個(gè)線(xiàn)程在處理布局,附加程序以及所有其他與日志記錄相關(guān)的組件。 因此,在移交之后,您將成為單線(xiàn)程的,并且您無(wú)需再擔(dān)心任何線(xiàn)程問(wèn)題,例如死鎖和活動(dòng)性等。”
“您可以更進(jìn)一步,使您的業(yè)務(wù)邏輯完全單線(xiàn)程化,并使用干擾器進(jìn)行所有I / O或與外部系統(tǒng)的通信。 沒(méi)有鎖爭(zhēng)用的單線(xiàn)程業(yè)務(wù)邏輯可以非常快。 LMAX的結(jié)果(600萬(wàn)筆事務(wù)/秒,延遲少于10毫秒)是不言而喻的。”
閱讀雷姆科的信息,我學(xué)到了三件事。
- 首先,我必須學(xué)習(xí)有關(guān)Java性能的更多信息。
- 其次,我絕對(duì)想讓我的應(yīng)用程序使用Log4j2。首先,我將在經(jīng)常使用的Struts 2應(yīng)用程序中啟用它。
- 第三,使用LMAX Disruptor的Web應(yīng)用程序框架可能會(huì)讓我們震驚。
我要非常感謝您和一個(gè)擁抱Remko Popma,感謝他們回答我的問(wèn)題并與我一起撰寫(xiě)此博客文章。 所有錯(cuò)誤都是我自己的。
雷姆波波瑪
  二十年前,雷姆科(Remko)來(lái)到日本,以提高圍棋比賽的水平。 不知何故他再也沒(méi)有回來(lái)。 Remko開(kāi)始為日本軟件公司進(jìn)行軟件開(kāi)發(fā),短暫地?fù)?dān)任自由開(kāi)發(fā)人員,與日本合作伙伴一起經(jīng)營(yíng)了一家軟件公司,現(xiàn)在正領(lǐng)導(dǎo)瑞穗證券IT的算法交易開(kāi)發(fā)。 他與妻子Tomoe和兒子Tobias一起住在東京。 
翻譯自: https://www.javacodegeeks.com/2013/07/log4j-2-performance-close-to-insane.html
總結(jié)
以上是生活随笔為你收集整理的Log4j 2:性能接近疯狂的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: Mockito – JAXB的RETUR
- 下一篇: 安卓是谷歌的吗(安卓是谷歌的)
