Apache Camel 3.1 –更多骆驼核心优化(第2部分)
我以前曾在博客中介紹我們在下一個Camel 3.1版本(第1部分)中所做的優(yōu)化 。
今天,我想發(fā)布大約4周后的最新狀態(tài)更新。
我們集中在三個方面優(yōu)化駱駝核心:
- 不必要的對象分配
- 不必要的方法調(diào)用
- 提高績效
換句話說,我們使Camel創(chuàng)建更少的對象,調(diào)用更少的方法并提高路由過程中的性能。
為了幫助識別駱駝核心中的這些問題,我們使用了一條簡單的駱駝路線:
來自timer:foo
記錄:foo
其他時候,我們專注于更長的路線:
來自timer:foo
記錄:foo1
記錄:foo2
記錄:foo3
…
登錄:fooN
或關(guān)注bean組件:
來自timer:foo
到bean:foo
等等。 我們還為計時器組件添加了一個不包含元數(shù)據(jù)的選項,因此消息不包含任何正文,標(biāo)頭或交換屬性。 這使我們可以專注于純路由引擎及其開銷。
因此,所有這些共同幫助確定了許多較小的改進(jìn)點,共同取得了巨大的成功。
tl:dr –顯示數(shù)字
好吧,讓我們先發(fā)布一些數(shù)字,然后再詳細(xì)說明已完成的工作。
對象分配–(5分鐘采樣)
駱駝2.25 2.9 M創(chuàng)建對象
駱駝3.0 55 M對象創(chuàng)建
駱駝3.1 1.8 M對象創(chuàng)建
好的,我們必須承認(rèn)Camel 3.0在路由過程中存在過多的對象分配問題。 沒有內(nèi)存泄漏,但是會創(chuàng)建很多不必要的對象。 我將在下面詳細(xì)說明原因。
但是,有趣的是駱駝2.25和3.1之間的增益(創(chuàng)建的對象減少40%)。
方法調(diào)用–(5分鐘采樣)
駱駝2.25 139種不同的駱駝使用方法
駱駝3.0 167種不同的駱駝使用方法
Camel 3.1使用84種不同的Camel方法
上表列出了Camel在路由過程中從Camel調(diào)用的方法數(shù)量。 數(shù)據(jù)不包括JDK中的所有方法。 由于我們無法優(yōu)化它們,但是我們可以優(yōu)化Camel源代碼。
從表中可以看出,我們已有改進(jìn)。 駱駝3.1的使用率不到3.0的一半,比駱駝2.2.5的使用率低40%。
駱駝3.0
好的,所以Camel 3.0在使用過多內(nèi)存方面存在問題。 一個重要的原因是新的反應(yīng)式執(zhí)行器現(xiàn)在可以通過事件循環(huán)執(zhí)行路由中的每個步驟,方法是將任務(wù)移交給隊列,并讓工作人員執(zhí)行任務(wù)。 因此,此切換現(xiàn)在需要創(chuàng)建其他對象并將任務(wù)存儲在隊列中等。
最大的一些成功是避免創(chuàng)建TRACE日志消息,不幸的是,無論是否啟用了TRACE日志記錄級別,始終都會創(chuàng)建該消息。 另一個大勝利是避免使用子元素創(chuàng)建路由過程的toString表示形式。 取而代之的是,駱駝現(xiàn)在只輸出進(jìn)程的id,這是一個快速的操作,并且不分配新對象。
另一個問題是使用java.util.stream的新代碼。 這既是祝福也是詛咒(主要是對快速代碼的詛咒)。 因此,通過使用普通的for循環(huán),if結(jié)構(gòu)并在核心路由引擎的關(guān)鍵部分避免使用java.util.stream,我們減少了對象分配。
Camel 3也是高度模塊化的,例如,在Camel 2.x中,我們將所有類都放在同一類路徑中,并且可以使用instanceof檢查。 因此,在Camel 3中,我們有一些代碼在執(zhí)行此類檢查時表現(xiàn)很差(再次是Java util流)。
另一個問題是被動執(zhí)行器,它使用LinkedList作為隊列。 因此,如果您有任務(wù)進(jìn)入隊列并且工作人員以相同的速度處理它們,因此隊列為空/耗盡,那么LinkedList的性能會很差,因為它會不斷分配/釋放對象。 通過切換到預(yù)分配大小為16的ArrayQueue,則隊列中始終有空間容納任務(wù),并且不會發(fā)生分配/取消分配。
還有更多優(yōu)化,但是上面提到的優(yōu)化可能是最大的問題。 然后,許多較小的優(yōu)化組合在一起。
許多較小的優(yōu)化
駱駝的UUID生成器正在使用一些字符串連接,這會花費很多。 我們減少了在消息和工作單元中生成UUID的需求,因此每個交換只生成1個。
駱駝路由引擎中的內(nèi)部建議(建議= AOP之前/之后)。 這些建議中的一些具有從前到后都需要保留的狀態(tài),這意味著需要存儲對象。 在我們?yōu)樗薪ㄗh分配一個數(shù)組之前,即使對于那些沒有狀態(tài)的建議也是如此,因此存儲了null。 現(xiàn)在,我們僅分配具有狀態(tài)的建議的確切數(shù)目的數(shù)組。 (非常小的勝利,例如object [6] vs object [2]等,但這是在駱駝路線中的每一步發(fā)生的,所以總的來說是合計的。) 另一個勝利是,如果不需要內(nèi)部路由處理器,則避免在UnitOfWork周圍進(jìn)行AOP。 這避免了額外的方法調(diào)用,并為after任務(wù)分配了一個回調(diào)對象。 由于所有這些都發(fā)生在路由的每個步驟中,因此是一個很好的改進(jìn)。
一些最常用的EIP已經(jīng)過優(yōu)化。 例如
允許您使用其他MEP將消息發(fā)送到端點(但是很少使用)。 現(xiàn)在,EIP會檢測到此情況,并避免創(chuàng)建用于恢復(fù)MEP的回調(diào)對象。 管道EIP(例如,當(dāng)您執(zhí)行->到-> to時)也對使用索引計數(shù)器而不是java.util.Iterator進(jìn)行了一些改進(jìn),因為后者分配了一個額外的對象
駱駝還有一個秒表,它使用java.util.Date來存儲時間。 已對其進(jìn)行優(yōu)化以使用長值。
另一個改進(jìn)是事件通知。 現(xiàn)在,我們會預(yù)先計算其是否正在使用中,并避免在與路由消息相關(guān)的事件中一起調(diào)用它們。 順便說一句,在Camel 3.0中,事件通知程序被重構(gòu)為使用Java 8 Supplier的API和許多精美的API,但是所有這些都會產(chǎn)生大量開銷。 在Camel 3.1中,我們已將通知程序恢復(fù)為與以前在Camel 2.x中一樣,并進(jìn)行了其他優(yōu)化。
因此,讓我以說……結(jié)束這個博客。 太棒了 Camel 3.1將使用更少的內(nèi)存,通過不調(diào)用太多方法來執(zhí)行得更快(請記住,我們可能不得不移動一些需要調(diào)用的代碼,但是以不同的方式執(zhí)行此操作,以避免調(diào)用太多的方法)。
在涉及的源代碼方面,最大的變化之一是從使用ServiceSupport(Camel中很多東西的基類)中的基于實例的記錄器切換為使用靜態(tài)記錄器實例。 這意味著將創(chuàng)建更少的Logger對象,這也是一種更好的做法。
更好的性能
其他改進(jìn)是,我們將駱駝作為交換屬性保留的某些內(nèi)部狀態(tài)直接移到了Exchange的字段中。 這樣可以避免在屬性映射中存儲鍵/值,但是我們可以使用諸如boolean,int等原語。由于通過getter獲取布爾值要比通過鍵在Map中查找值更快,因此這樣做的效果也更好。
實際上,在Camel 3.1中,然后在常規(guī)路由期間,Camel不會從交換屬性中查找任何此類狀態(tài),這意味著沒有方法調(diào)用。 仍然有一些狀態(tài)存儲為交換屬性(將來可能會改善其中一些狀態(tài),但是這些狀態(tài)中的大多數(shù)僅很少使用)。 我們優(yōu)化的是在路由過程中始終檢查和使用的狀態(tài)。
交換getProperty(5分鐘采樣)
駱駝2.25 572598 getPropety(字符串)
駱駝2.25 161502 getPropety(字符串,對象)
駱駝2.25 161502 getPropety(字符串,對象,類)
駱駝2.25 141962 getPropeties()
駱駝3.0 574944 getProperty(字符串)
Camel 3.0 167904 getPropety(字符串,對象)
駱駝3.0 167904 getPropety(字符串,對象,類)
駱駝3.0 91584 getPropeties()
駱駝3.1 0 getProperty(String)
駱駝3.1 0 getPropety(String,Object)
駱駝3.1 0 getPropety(String,Object,Class)
駱駝3.1 0 getPropeties()
如您所見,Camel 2.25和3.0查找了很多這種狀態(tài)。 在Camel 3.1中,我們對此進(jìn)行了極大的優(yōu)化,并且根本沒有查找-就像說狀態(tài)以原始類型存儲在Exchange上一樣,JDK可以內(nèi)聯(lián)并執(zhí)行得非常快。
以下屏幕截圖顯示了駱駝2.25和3.1。 (3.1的屏幕截圖與昨天相比略有過時,此后我們對Camel進(jìn)行了優(yōu)化)。 請參見下面的屏幕截圖:
好的,還有許多其他較小的優(yōu)化,在撰寫此博客時,我目前正在研究一個優(yōu)化。 好的,讓我結(jié)束這個博客,并保存第3部分的詳細(xì)信息。
翻譯自: https://www.javacodegeeks.com/2020/02/apache-camel-3-1-more-camel-core-optimizations-coming-part-2.html
總結(jié)
以上是生活随笔為你收集整理的Apache Camel 3.1 –更多骆驼核心优化(第2部分)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java lambda函数_Java S
- 下一篇: 在AWS第1部分中使用Terraform