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