摘要:本文將介紹如何進(jìn)行序列化性能檢測(cè)的重要性以及在分布式系統(tǒng)中的應(yīng)用。另一個(gè)鮮有人知的特點(diǎn)就是可被序列化。所以當(dāng)?shù)氖褂迷斐尚阅軉?wèn)題時(shí),就要使用備選方案。下面就是當(dāng)在中序列化時(shí),非采集的的情況。
本文將介紹如何進(jìn)行 Java Lambdas 序列化性能檢測(cè)、Lambdas 的重要性以及 Lambdas 在分布式系統(tǒng)中的應(yīng)用。
Lambdas 表達(dá)式是 Java 8 中萬(wàn)眾期待的新特性,其若干用途包括:
為匿名內(nèi)部類(lèi)減少所需樣本代碼。
縮小值的作用域。Lambdas 表達(dá)式中的 this 不會(huì)涉及到外部類(lèi),減少了內(nèi)存泄露。
輕松集成現(xiàn)有 API 與新的 Streams API。
Lambdas 另一個(gè)鮮有人知的特點(diǎn)就是可被序列化。
為什么對(duì) Lambda 序列化?序列化有益于對(duì)象的狀態(tài)持久化和網(wǎng)絡(luò)傳輸。 Lambdas 應(yīng)該盡可能無(wú)狀態(tài),這樣就可以保存 Lambdas ,但這并不是典型的用例。
Lambdas 表達(dá)式的目的是給程序庫(kù)傳遞代碼片段,使之與庫(kù)中正在運(yùn)行的程序交互。但是如果程序庫(kù)支持像 Chronicle Engine 這樣的分布式系統(tǒng),那又會(huì)怎么樣?
什么是 Chronicle Engine?Chronicle Engine 是一個(gè)庫(kù),可讓用戶使用各自的應(yīng)用程序遠(yuǎn)程訪問(wèn)數(shù)據(jù)結(jié)構(gòu),無(wú)論是用 Java、C# 客戶端,還是用 NFS 文件系統(tǒng)。該庫(kù)還支持存儲(chǔ)和持久化數(shù)據(jù),也支持復(fù)制。
分布式系統(tǒng)中的 Lambdas對(duì)于某些局部運(yùn)行的操作,使用 Lambdas 執(zhí)行不失為一種簡(jiǎn)單可行的方法。示例操作如下:
MapViewmap = acquireMap(“map-name”, String.class, Long.class); map.put(“key”, 1); long ret = map.applyToKey(“key”, v -> v + 1); // ret == 2
這里沒(méi)有必要知道數(shù)據(jù)的具體存儲(chǔ)位置,如果是遠(yuǎn)程服務(wù)器,就會(huì)在那臺(tái)服務(wù)器上對(duì) Lambda 序列化,然后執(zhí)行,并將結(jié)果返回。
上圖顯示了 OneAPM 如何監(jiān)控和讓 Java 應(yīng)用之間的調(diào)用關(guān)系可視化。
Capturing Lambda不獲取字段的 Lambda 可以被 Java 更高效地處理,因?yàn)槊總€(gè)實(shí)例都一樣,所以并不需要每次都創(chuàng)建新的對(duì)象。但是,若編譯時(shí) Lambda 獲取到未知值,就需要?jiǎng)?chuàng)建新的對(duì)象,并將獲取的值保存。
Non capturing Lambda
FunctionappendStar = s -> s + "*"
Capturing Lambda
String star = "*"; Function可序列化的 LambdasappendStar = s -> s + star;
Lambdas 默認(rèn)是不可序列化的,必須實(shí)現(xiàn)一種可序列化的接口。可以使用強(qiáng)制轉(zhuǎn)換把接口類(lèi)型轉(zhuǎn)換為所需類(lèi)型的一種方式。
FunctionappendStar = (Function & Serializable) (s -> s + star);
筆者個(gè)人不喜歡這樣做,因?yàn)檫@樣會(huì)破壞減少代碼的目標(biāo)。一個(gè)解決的方法就是定義自己所需的可序列化的接口。
@FunctionalInterface public interface SerializableFunction extends Function, Serializable {
這就需要如下所寫(xiě):
SerializableFunctionappendStar = s -> s + star;
或者按照這種方法寫(xiě)入:
R applyToKey(K key, @NotNull SerializableFunction function) {
該庫(kù)的調(diào)用者就可以如下所寫(xiě),而不需要任何樣本代碼。
String s = map.applyToKey(“key”, s-> s + “*”);Lambdas 的實(shí)時(shí)查詢(xún)
利用序列化的 Lambdas,可進(jìn)行如下所示的實(shí)時(shí)查詢(xún):
// print the last name of all the people in NYC acquireMap(“people”, String.class, Person.class).query() .filter(p -> p.getCity().equals(“NYC”)) // executed on the server .map(p → p.getLastName()) // executed on the server .subscribe(System.out::println); // executed on the client.
可查詢(xún)接口是必需的,因此過(guò)濾器 Predicate 和 map 函數(shù)也必須隱式可序列化。如果需要使用 Streams API,那就要使用早期較為復(fù)雜的數(shù)據(jù)類(lèi)型轉(zhuǎn)換函數(shù) cast。
序列化 Lambdas 的性能筆者曾經(jīng)在一個(gè)字符串中寫(xiě)入符號(hào)“*”,并使用 JMH 對(duì)簡(jiǎn)單的序列化的和反序列化的 Lambda 進(jìn)行時(shí)延采樣,然后比較采集和非采集兩種情況下的時(shí)延,發(fā)送枚舉時(shí)兩種情況下的時(shí)延也一并比較。代碼和結(jié)果如下表所示:
99.99%的時(shí)延意味著該試驗(yàn)的99.99%都是在時(shí)延之中。時(shí)間都用微秒計(jì)算。
Test | Typical latency | 99.99% latency |
---|---|---|
Java Serialization, non-capturing | 33.9 μs | 215 μs |
Java Serialization, capturing | 36.3 μs | 704 μs |
Java Serialization, with an enum | 7.9 μs | 134 μs |
Chronicle Wire (Text), non-capturing | 20.4 μs | 147 μs |
Chronicle Wire (Text), capturing | 22.5 μs | 148 μs |
Chronicle Wire (Text), with an enum | 1.2 μs | 5.9 μs |
Chronicle Wire (Binary), non-capturing | 11.7 μs | 103 μs |
Chronicle Wire (Binary), capturing | 12.7 μs | 135 μs |
Chronicle Wire (Binary), with an enum | 1.0 μs | 1.2 μs |
使用 Lambda 是很簡(jiǎn)單,但它效率不高時(shí),就需要找一個(gè)備選方案。所以當(dāng) Lambda 的使用造成性能問(wèn)題時(shí),就要使用備選方案。
enum Functions implements SerializableFunction{ APPEND_STAR { @Override public String apply(String s) { return s + "*"; } } }
為考察使用枚舉所起到的作用,可以比較發(fā)送到服務(wù)器的數(shù)據(jù)量的多少,在那里可以看到所有序列化的數(shù)據(jù)。
下面就是當(dāng)在 TextWire 中序列化時(shí),非采集的 Lambda 的情況。(基于 YAML)
!SerializedLambda { cc: !type lambda.LambdaSerialization, fic: net/openhft/chronicle/core/util/SerializableFunction, fimn: apply, fims: (Ljava/lang/Object;)Ljava/lang/Object;, imk: 6, ic: lambda/LambdaSerialization, imn: lambda$textWireSerialization$ea1ad110$1, ims: (Ljava/lang/String;)Ljava/lang/String;, imt: (Ljava/lang/String;)Ljava/lang/String;, ca: [ ] }
枚舉序列化如下所示:
!Functions APPEND_STAR
注意:當(dāng)需要采集某些值時(shí),不可以使用枚舉。我們要做的就是讓你通過(guò)傳遞有附加參數(shù)的枚舉,以獲得最有效的組合。
使用枚舉就像存儲(chǔ)過(guò)程用枚舉代替 Lambdas 的一個(gè)好處就是,可以跟蹤所有功能客戶執(zhí)行和整合的方式。某些函數(shù)使用廣泛,運(yùn)用枚舉使得修復(fù)任一多帶帶函數(shù)中產(chǎn)生的bug更為容易,因此會(huì)被經(jīng)常使用。舉一個(gè)簡(jiǎn)單的例子,MapFunction 起初有很多不同的 Lambdas,而現(xiàn)在已經(jīng)被歸為一類(lèi)。
結(jié)論如果所使用的 API 支持,可將 Lambdas 用于分布式應(yīng)用程序。如果需要附加的性能,也可以使用枚舉。
原文地址:https://dzone.com/articles/measuring-the-serialization-performance-of-lambdas
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65313.html
摘要:這減輕了手動(dòng)重復(fù)執(zhí)行相同基準(zhǔn)測(cè)試的痛苦,并簡(jiǎn)化了獲取結(jié)果的流程。處理項(xiàng)目的代碼并從標(biāo)有注釋的方法處生成基準(zhǔn)測(cè)試程序。用和運(yùn)行該基準(zhǔn)測(cè)試得到以下結(jié)果。同時(shí),和的基線測(cè)試結(jié)果也有略微的不同。 Java 8 已經(jīng)發(fā)布一段時(shí)間了,許多開(kāi)發(fā)者已經(jīng)開(kāi)始使用 Java 8。本文也將討論最新發(fā)布在 JDK 中的并發(fā)功能更新。事實(shí)上,JDK 中已經(jīng)有多處java.util.concurrent 改動(dòng),但...
摘要:背景許多時(shí)候需要對(duì)比不同的框架或工具或算法,選擇使用性能更優(yōu)的那一個(gè)。通常的做法是但這樣的做法非常不嚴(yán)謹(jǐn),因?yàn)楫?dāng)獨(dú)立頻繁運(yùn)行這一小塊代碼時(shí),可能會(huì)針對(duì)性的做一些優(yōu)化工作,而在實(shí)際的生產(chǎn)環(huán)境中是不會(huì)有此優(yōu)化的。 背景 許多時(shí)候需要對(duì)比不同的框架或工具或算法, 選擇使用性能更優(yōu)的那一個(gè)。通常的做法是 long start = System.currentTimeMillis(); for(...
摘要:分析性能的影響但是需要注意時(shí)間單位,只是微秒而已,毫秒的千分之一秒的百萬(wàn)分之一。在這種情況下,優(yōu)化毫秒的性能隱患無(wú)異于撿了芝麻丟了西瓜。 同步自:https://sulin.me/2019/T2ZXZB.... 在分布式系統(tǒng)開(kāi)發(fā)中,我們經(jīng)常需要將各種各樣的狀態(tài)碼、錯(cuò)誤信息傳遞給最外層的調(diào)用方,這個(gè)調(diào)用方通常是http/api接口,錯(cuò)誤信息比如登錄失效、參數(shù)錯(cuò)誤等等。 最外層接口暴露的...
摘要:摘要添加了表達(dá)式閉包和特性支持,包括方法的引用,增強(qiáng)類(lèi)型推斷,和虛擬擴(kuò)展方法。圍繞的語(yǔ)言功能支持包括虛擬擴(kuò)展方法,這將使接口的源代碼和二進(jìn)制兼容的方式演變升級(jí)。 Author:Joseph D. Darcy Organization:Oracle Owner:Brian Goetz Created:2011/11/1 Updated:2013/2/21 Type:Feature Sta...
閱讀 4319·2021-09-24 09:47
閱讀 1192·2021-09-03 10:33
閱讀 2077·2019-08-30 11:13
閱讀 1039·2019-08-30 10:49
閱讀 1762·2019-08-29 16:13
閱讀 2052·2019-08-29 11:28
閱讀 3102·2019-08-26 13:31
閱讀 3638·2019-08-23 17:14