FastJson性能優(yōu)化知多少

FastJson是一個(gè)近幾年非常熱門的第三方j(luò)ava庫(kù)桐磁,它以它強(qiáng)大的功能和出色的性能表現(xiàn)而廣為人知。那么,究竟為何FastJson能做到如此fast呢尉姨?它有什么秘訣?或者說(shuō)吗冤,它做了哪些優(yōu)化工作使得性能提升如此之多又厉?本文從作者的理解出發(fā)九府,結(jié)合代碼詳細(xì)分析FastJson的性能優(yōu)化方法和優(yōu)秀的編程實(shí)踐。

FastJson簡(jiǎn)介

首先來(lái)看看什么是FastJson覆致。

引用自github [https://github.com/alibaba/fastjson]:

Fastjson is a Java library that can be used to? convert Java Objects into their JSON representation. It can also be used to? convert a JSON string to an equivalent Java object. Fastjson can work with? arbitrary Java objects including pre-existing objects that you do not have? source-code of.

簡(jiǎn)單總結(jié)下就是:

1. Fastjson是一個(gè)java庫(kù)集合(server?side and android client)侄旬;

2. Fastjson可以將java對(duì)象和JSON字符串來(lái)回轉(zhuǎn)換;

? ? Ps. JSON(JavaScript?Object Notation, JavaScript對(duì)象表示法)是一種輕量級(jí)的數(shù)據(jù)交換格式煌妈。

3. Fastjson可以操作任何java對(duì)象儡羔,即使是一些預(yù)先存在的沒有源碼的對(duì)象。

Fastjson用途

Fastjson可以將java對(duì)象和JSON字符串來(lái)回轉(zhuǎn)換璧诵,所以它能被用作:

1. 對(duì)象的序列化后存儲(chǔ)(memcache, redis等)汰蜘、傳輸(web,?socket);

2. 接收數(shù)據(jù)后對(duì)象的還原即反序列化之宿。

Fastjson的牛掰之處

幾個(gè)主流json轉(zhuǎn)換工具的功能性能對(duì)比(摘自網(wǎng)絡(luò)):

幾個(gè)常用序列化工具的處理速度對(duì)比(摘自網(wǎng)絡(luò)):

從上面兩個(gè)表的對(duì)比數(shù)據(jù)來(lái)看鉴扫,

1.fastjson性能表現(xiàn)最好,解析速度最快澈缺,而且功能已經(jīng)足夠強(qiáng)大坪创,推薦使用;

2.轉(zhuǎn)換對(duì)象極其復(fù)雜情況下姐赡,可以考慮使用gson莱预。

Fastjson提供什么功能/特性

以下幾點(diǎn)摘自github [https://github.com/alibaba/fastjson]

1. Provide best performance in serverside and android client.

? ? 提供服務(wù)器端、安卓客戶端兩種解析工具项滑,性能表現(xiàn)業(yè)界最佳依沮。

2. Provide simple toJSONString() andparseObject() methods to convert Java objects to JSON and vice-versa

? ? 簡(jiǎn)單易用,調(diào)用toJSONString方法即可將對(duì)象轉(zhuǎn)換成json字符串枪狂,parseObject方法則反過(guò)來(lái)將json字符串轉(zhuǎn)換成對(duì)象危喉。

3. Allow pre-existing unmodifiableobjects to be converted to and from JSON

? ? 允許轉(zhuǎn)換預(yù)先存在的無(wú)法修改的對(duì)象(只有class、無(wú)源代碼)州疾。

4. Extensive support of Java Generics

? ? Java泛型的廣泛支持辜限。

5. Allow custom representations forobjects

? ? 允許對(duì)象的自定義表示、允許自定義序列化類严蓖。

6. Support arbitrarily complexobjects (with deep inheritance hierarchies and extensive use of generic types)

? ? 支持任意復(fù)雜對(duì)象(具有深厚的繼承層次和廣泛使用的泛型類型)薄嫡。

Fastjson的性能優(yōu)化

那么接下來(lái),我們分析下為什么Fastjson能做到這么快颗胡。分序列化和反序列化兩個(gè)過(guò)程分析毫深。

序列化

1. IdentityHashMap緩存各種序列化處理類,包括各種基本對(duì)象毒姨、集合對(duì)象哑蔫、第三方對(duì)象、自定義對(duì)象,方便序列化處理類的快速查找闸迷、避免JavaBeanSerializer的反復(fù)創(chuàng)建嵌纲。

更加詳細(xì)代碼請(qǐng)參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/serializer/SerializeConfig.java

2. 使用ThreadLocal來(lái)存儲(chǔ)序列化過(guò)程中不斷append的字符串,減少內(nèi)存分配和gc稿黍,從而提高性能疹瘦。

3. 用類StringBuilder方式進(jìn)行字符串操作,配合ThreadLocal實(shí)現(xiàn)線程安全的StringBuilder巡球。

更加詳細(xì)代碼請(qǐng)參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java

4. 缺省啟用sort field輸出言沐,為deserialize優(yōu)化做準(zhǔn)備。

具體為什么開啟了排序的輸出能夠提升對(duì)象還原(反序列化)的效率酣栈,請(qǐng)查閱下面反序列化的“快速匹配”险胰。

5. 使用asm高效反射,fastjson-asm基于objectweb asm?3.3.1改造矿筝,只保留必要的部分起便,不到2000行代碼。具體代碼可參考:https://github.com/alibaba/fastjson/tree/master/src/main/java/com/alibaba/fastjson/asm

反序列化

1. IdentityHashMap緩存各種反序列化處理類窖维,包括基本對(duì)象榆综、集合對(duì)象、第三方對(duì)象铸史、自定義對(duì)象鼻疮,方便反序列化類的快速查找、避免JavaBeanDeserializer的反復(fù)創(chuàng)建琳轿。代碼與序列化的處理類緩存相似判沟,具體請(qǐng)參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java

2. 讀取token基于預(yù)測(cè)。在反序列化一個(gè)json字符串時(shí)崭篡,下一個(gè)字符一般情況下是可以預(yù)估的挪哄。比如字符}之后最有可能出現(xiàn)的是“,”、“]”琉闪、“}”或者結(jié)束符迹炼,有計(jì)劃、有預(yù)測(cè)地判斷token將能提升不少性能塘偎。于是Fastjson在實(shí)現(xiàn)的時(shí)候?qū)懥诉@樣一個(gè)函數(shù):

更加詳細(xì)的代碼請(qǐng)參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/parser/JSONLexerBase.java

3. 快速匹配疗涉。在Fastjson反序列化過(guò)程中,有一個(gè)非常有用的效率改進(jìn)方法是有序json的快速匹配吟秩。所謂有序json就是json字符串中的key是按照字符排序好了的。上面已經(jīng)說(shuō)過(guò)绽淘,F(xiàn)astjson的序列化默認(rèn)是按照key的順序進(jìn)行的涵防,因此做反序列化時(shí)候,F(xiàn)astjson采用一種優(yōu)化算法,就是假設(shè)key/value的內(nèi)容是有序的壮池,讀取的時(shí)候只需要做key的匹配偏瓤,而不需要把key從輸入中讀取出來(lái)。通過(guò)這個(gè)優(yōu)化椰憋,使得Fastjson在處理json文本的時(shí)候厅克,少讀取超過(guò)50%的token,這個(gè)是一個(gè)十分關(guān)鍵的優(yōu)化算法橙依≈ぶ郏基于這個(gè)算法,使用asm實(shí)現(xiàn)窗骑,性能提升十分明顯女责,超過(guò)300%的性能提升。例:

{"id":123,"name":"testJson","salary":11}

在上面例子看创译,虛線標(biāo)注的三個(gè)部分是key抵知,如果key_id、key_name软族、key_salary這三個(gè)key是順序的刷喜,就可以做優(yōu)化處理,這三個(gè)key不需要被讀取出來(lái)立砸,只需要比較就可以了掖疮。

這種算法分兩種模式,一種是快速模式仰禽,一種是常規(guī)模式氮墨。快速模式是假定key是順序的吐葵,能快速處理规揪,如果發(fā)現(xiàn)不能夠快速處理,則退回常規(guī)模式温峭。保證性能的同時(shí)猛铅,不會(huì)影響功能。在這個(gè)例子中凤藏,常規(guī)模式需要處理13個(gè)token奸忽,快速模式只需要處理6個(gè)token。實(shí)現(xiàn)代碼片段如下:

詳細(xì)代碼請(qǐng)參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java

4. 使用asm高效反射

同上序列化的asm反射揖庄。

5. symbolTable算法緩存關(guān)鍵字栗菜,避免創(chuàng)建新的字符串對(duì)象。試想一下蹄梢,假設(shè)一個(gè)json字符串中疙筹,有成千上萬(wàn)個(gè)同樣的json對(duì)象的數(shù)組,那么在轉(zhuǎn)換過(guò)程中,如果不對(duì)這些json對(duì)象中的key做緩存而咆,將會(huì)存在成千上萬(wàn)個(gè)同樣的字符串對(duì)象(值相同)霍比,顯然這樣會(huì)浪費(fèi)極大的內(nèi)存和性能。于是Fastjson寫了一個(gè)SymbolTable類來(lái)緩存這些臨時(shí)字符串符號(hào)變量暴备。

更加詳細(xì)的代碼請(qǐng)參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/parser/SymbolTable.java

最后

除了性能優(yōu)化之外悠瞬,F(xiàn)astjson還有許多編程思想和實(shí)踐是值得我們?nèi)W(xué)習(xí)的,只要用心去研究和挖掘涯捻,必定能學(xué)到很多能夠?qū)W以致用東西浅妆。當(dāng)然,也只有認(rèn)真去學(xué)習(xí)了并嘗試在平時(shí)項(xiàng)目開發(fā)過(guò)程中運(yùn)用汰瘫,才能夠真正提升自己的代碼水平狂打。后期有機(jī)會(huì)再給大家分享下Fastjson在ASM高效反射和泛型支持上的獨(dú)具匠心之處,請(qǐng)大家拭目以待混弥。J

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末趴乡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蝗拿,更是在濱河造成了極大的恐慌晾捏,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哀托,死亡現(xiàn)場(chǎng)離奇詭異惦辛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)仓手,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門胖齐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嗽冒,你說(shuō)我怎么就攤上這事呀伙。” “怎么了添坊?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵剿另,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我贬蛙,道長(zhǎng)雨女,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任阳准,我火速辦了婚禮氛堕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘野蝇。我一直安慰自己岔擂,他們只是感情好位喂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布浪耘。 她就那樣靜靜地躺著乱灵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪七冲。 梳的紋絲不亂的頭發(fā)上痛倚,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音澜躺,去河邊找鬼蝉稳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛掘鄙,可吹牛的內(nèi)容都是我干的耘戚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼操漠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼收津!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起浊伙,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤撞秋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后嚣鄙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吻贿,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年哑子,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舅列。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卧蜓,死狀恐怖帐要,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烦却,我是刑警寧澤宠叼,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站其爵,受9級(jí)特大地震影響冒冬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜摩渺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一简烤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摇幻,春花似錦横侦、人聲如沸挥萌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)引瀑。三九已至,卻和暖如春榨馁,著一層夾襖步出監(jiān)牢的瞬間憨栽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工翼虫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屑柔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓珍剑,卻偏偏與公主長(zhǎng)得像掸宛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子招拙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容