Java序列化與JSON序列化大比拼
一、背景
有項(xiàng)目需要傳輸Map結(jié)構(gòu)的數(shù)據(jù),有人傾向用Java序列化來做,有人傾向用JSON的序列化來做。所以我們還是比比吧。
Java觀點(diǎn):Object2Object,使用時(shí)簡(jiǎn)單快速。
JSON觀點(diǎn):JSON格式與語言無關(guān),擴(kuò)展性強(qiáng),速度也應(yīng)該不慢。
大家可能對(duì)Java序列化都有一個(gè)錯(cuò)誤的認(rèn)識(shí),認(rèn)為Java序列化比JSON的序列化效率高并且序列化的數(shù)據(jù)小,其實(shí)實(shí)際上并不一定是這樣,我這次就想通過實(shí)際測(cè)試來解開這個(gè)謎團(tuán)。
二、測(cè)試方式
測(cè)試同一個(gè)Map<String,Object>并序列化為byte[],并再將byte[]反序列化為 Map<String,Object>的過程。Object中包括 String,Integer,Long,Boolean,F(xiàn)loat,Double常規(guī)類型的數(shù)據(jù)。
序列化:Map<String,Object> -> byte[]
反序列化:byte[] -> Map<String,Object>
測(cè)試各種大小不同的Map,并循環(huán)執(zhí)行同一操作N次,來得到一個(gè)相對(duì)穩(wěn)定的線性結(jié)果。
三、比較的對(duì)象
JAVA:
手寫Java(1.6.0_32)與Common Lang3(3.1)的SerializationUtils。
JSON:
將采用Gson(2.2.2)與json-smart(2.0-RC2)兩種不同的JSON解析器。json-smart號(hào)稱是速度最快的JSON解析器。
四、比較結(jié)果
Map大小(10-100)循環(huán)10萬次
序列化時(shí)間比較(y為序列化時(shí)間ms)
反序列化時(shí)間比較(y為反序列化時(shí)間ms)
序列化時(shí)間匯總比較(y為序列化與反序列化總時(shí)間ms)
序列化后byte大小比較(由于同類線重合顯示為2條線)
Map大小(100-1000)循環(huán)1萬次
序列化時(shí)間比較(y為序列化時(shí)間ms)
反序列化時(shí)間比較(y為反序列化時(shí)間ms)
序列化時(shí)間匯總比較(y為序列化與反序列化總時(shí)間ms)
序列化后byte大小比較(由于同類線重合顯示為2條線)
比較總結(jié)
Map在小于100時(shí):
Java的反序列化時(shí)的性能要比Java序列化時(shí)性能差很多,1.5倍左右差距。
JSON序列化性能明顯由于Java序列化性能,尤其是反序列化過程。并且序列化后的數(shù)據(jù)大小也是JSON格式的小。
Map在大于100小于1000時(shí):
Java的反序列化時(shí)的性能并沒有隨Map的大小變化而變差。
JSON陣營中Gson在序列化過程中,比Java只快了那么一點(diǎn)點(diǎn)。在反序列化過程中Gson開始領(lǐng)先與Java,但在Map的大小過700多以后,Gson的反序列化性能比Java要慢。但JSON陣營中的json-smart依然表現(xiàn)出色完全是兩個(gè)級(jí)別。
并不是Java的序列化速度總是最快體積最小,Java需要考慮對(duì)象類型,屬性類型與內(nèi)部對(duì)象信息等一系列對(duì)數(shù)據(jù)本身并不相關(guān)的內(nèi)容的處理。JSON以固定的格式,穩(wěn)定簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)大大簡(jiǎn)化了序列化過程,雖然也要?jiǎng)?chuàng)建新的Java數(shù)據(jù)對(duì)象但并不會(huì)比Java反序列化的速度慢。
從測(cè)試結(jié)果上看JSON的json-smart更適合項(xiàng)目的需要。
#p#
五、測(cè)試代碼源碼
SerializationTest接口
- package org.noahx.javavsjson;
- import java.util.Map;
- /**
- * Created with IntelliJ IDEA.
- * User: noah
- * Date: 3/8/13
- * Time: 9:59 PM
- * To change this template use File | Settings | File Templates.
- */
- public interface SerializationTest {
- public String getTestName();
- public Map<String, Object> testBytes2Map(byte[] bytes);
- public byte[] testMap2Bytes(Map<String, Object> map);
- }
JavaSerializationTest
- package org.noahx.javavsjson;
- import java.io.*;
- import java.util.Map;
- /**
- * Created with IntelliJ IDEA.
- * User: noah
- * Date: 3/8/13
- * Time: 10:05 PM
- * To change this template use File | Settings | File Templates.
- */
- public class JavaSerializationTest implements SerializationTest {
- @Override
- public String getTestName() {
- return "Java";
- }
- @Override
- public Map<String, Object> testBytes2Map(byte[] bytes) {
- Map<String, Object> result = null;
- try {
- ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
- ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream);
- result = (Map<String, Object>) inputStream.readObject();
- inputStream.close();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return result;
- }
- @Override
- public byte[] testMap2Bytes(Map<String, Object> map) {
- byte[] bytes = null;
- try {
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
- outputStream.writeObject(map);
- outputStream.close();
- bytes = byteArrayOutputStream.toByteArray();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return bytes;
- }
- }
CommonLang3SerializationTest
- package org.noahx.javavsjson;
- import org.apache.commons.lang3.SerializationUtils;
- import java.io.Serializable;
- import java.util.Map;
- /**
- * Created with IntelliJ IDEA.
- * User: noah
- * Date: 3/9/13
- * Time: 2:24 AM
- * To change this template use File | Settings | File Templates.
- */
- public class CommonLang3SerializationTest implements SerializationTest {
- @Override
- public String getTestName() {
- return "Commons Lang3";
- }
- @Override
- public Map<String, Object> testBytes2Map(byte[] bytes) {
- return (Map<String, Object>) SerializationUtils.deserialize(bytes);
- }
- @Override
- public byte[] testMap2Bytes(Map<String, Object> map) {
- return SerializationUtils.serialize((Serializable) map);
- }
- }
GsonSerializationTest
- package org.noahx.javavsjson;
- import com.google.gson.Gson;
- import java.io.UnsupportedEncodingException;
- import java.util.Map;
- /**
- * Created with IntelliJ IDEA.
- * User: noah
- * Date: 3/8/13
- * Time: 10:02 PM
- * To change this template use File | Settings | File Templates.
- */
- public class GsonSerializationTest implements SerializationTest {
- private Gson gson;
- public GsonSerializationTest() {
- gson = new Gson();
- }
- @Override
- public String getTestName() {
- return "Gson";
- }
- @Override
- public Map<String, Object> testBytes2Map(byte[] bytes) {
- Map<String, Object> result = null;
- try {
- result = gson.fromJson(new String(bytes, "UTF-8"), Map.class);
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return result;
- }
- @Override
- public byte[] testMap2Bytes(Map<String, Object> map) {
- String str = gson.toJson(map);
- byte[] bytes = null;
- try {
- bytes = str.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return bytes;
- }
- }
JsonSmartSerializationTest
- package org.noahx.javavsjson;
- import net.minidev.json.JSONObject;
- import net.minidev.json.JSONValue;
- import net.minidev.json.parser.ParseException;
- import java.io.UnsupportedEncodingException;
- import java.util.Map;
- /**
- * Created with IntelliJ IDEA.
- * User: noah
- * Date: 3/9/13
- * Time: 1:30 AM
- * To change this template use File | Settings | File Templates.
- */
- public class JsonSmartSerializationTest implements SerializationTest {
- @Override
- public String getTestName() {
- return "Json Smart";
- }
- @Override
- public Map<String, Object> testBytes2Map(byte[] bytes) {
- Map<String, Object> map = null;
- try {
- map = (Map<String, Object>) JSONValue.parseStrict((new String(bytes, "UTF-8")));
- } catch (ParseException e) {
- e.printStackTrace();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return map;
- }
- @Override
- public byte[] testMap2Bytes(Map<String, Object> map) {
- String str = JSONObject.toJSONString(map);
- byte[] result = null;
- try {
- result = str.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return result;
- }
- }
P.S.
我也測(cè)試過Map<String,String>固定數(shù)據(jù)類型value只為String的情況,這時(shí)Java與JSON的性能的差距會(huì)減小,但JSON序列化性能與數(shù)據(jù)大小還是占優(yōu)勢(shì),尤其是反序列化的速度JSON更出色。
Gson在數(shù)值反序列化后,因?yàn)镺bject無法確定類型,Map中的Long,Integer,F(xiàn)loat統(tǒng)一轉(zhuǎn)為了Double類型。
json-smart不一樣,如果整數(shù)超過Integer的范圍轉(zhuǎn)Long,沒有超過轉(zhuǎn)Integer。浮點(diǎn)Float轉(zhuǎn)為Double類型。