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

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

FastJson簡介

首先來看看什么是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é)下就是:

1. Fastjson是一個java庫集合(server?side and android client);

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

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

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

Fastjson用途

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

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

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

Fastjson的牛掰之處

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

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

從上面兩個表的對比數(shù)據(jù)來看,

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

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

Fastjson提供什么功能/特性

以下幾點摘自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

? ? 簡單易用,調(diào)用toJSONString方法即可將對象轉(zhuǎn)換成json字符串,parseObject方法則反過來將json字符串轉(zhuǎn)換成對象。

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

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

4. Extensive support of Java Generics

? ? Java泛型的廣泛支持。

5. Allow custom representations forobjects

? ? 允許對象的自定義表示、允許自定義序列化類。

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

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

Fastjson的性能優(yōu)化

那么接下來,我們分析下為什么Fastjson能做到這么快。分序列化和反序列化兩個過程分析。

序列化

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

更加詳細代碼請參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/serializer/SerializeConfig.java

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

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

更加詳細代碼請參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java

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

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

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緩存各種反序列化處理類,包括基本對象、集合對象、第三方對象、自定義對象,方便反序列化類的快速查找、避免JavaBeanDeserializer的反復(fù)創(chuàng)建。代碼與序列化的處理類緩存相似,具體請參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java

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

更加詳細的代碼請參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/parser/JSONLexerBase.java

3. 快速匹配。在Fastjson反序列化過程中,有一個非常有用的效率改進方法是有序json的快速匹配。所謂有序json就是json字符串中的key是按照字符排序好了的。上面已經(jīng)說過,F(xiàn)astjson的序列化默認是按照key的順序進行的,因此做反序列化時候,F(xiàn)astjson采用一種優(yōu)化算法,就是假設(shè)key/value的內(nèi)容是有序的,讀取的時候只需要做key的匹配,而不需要把key從輸入中讀取出來。通過這個優(yōu)化,使得Fastjson在處理json文本的時候,少讀取超過50%的token,這個是一個十分關(guān)鍵的優(yōu)化算法。基于這個算法,使用asm實現(xiàn),性能提升十分明顯,超過300%的性能提升。例:

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

在上面例子看,虛線標注的三個部分是key,如果key_id、key_name、key_salary這三個key是順序的,就可以做優(yōu)化處理,這三個key不需要被讀取出來,只需要比較就可以了。

這種算法分兩種模式,一種是快速模式,一種是常規(guī)模式。快速模式是假定key是順序的,能快速處理,如果發(fā)現(xiàn)不能夠快速處理,則退回常規(guī)模式。保證性能的同時,不會影響功能。在這個例子中,常規(guī)模式需要處理13個token,快速模式只需要處理6個token。實現(xiàn)代碼片段如下:

詳細代碼請參考: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)建新的字符串對象。試想一下,假設(shè)一個json字符串中,有成千上萬個同樣的json對象的數(shù)組,那么在轉(zhuǎn)換過程中,如果不對這些json對象中的key做緩存,將會存在成千上萬個同樣的字符串對象(值相同),顯然這樣會浪費極大的內(nèi)存和性能。于是Fastjson寫了一個SymbolTable類來緩存這些臨時字符串符號變量。

更加詳細的代碼請參考:https://github.com/alibaba/fastjson/blob/master/src/main/java/com/alibaba/fastjson/parser/SymbolTable.java

最后

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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