为什么java内置序列化比Gson差?

时间:2014-01-25 06:53:50

标签: java performance serialization gson

我认为Java内置序列化的性能应该很好。与Gson相比,它不需要进行词法分析,它应该比Gson更快。

但在我的测试中,结果恰恰相反。看我的代码:

package cleancode;

import com.google.gson.Gson;

import java.io.*;

public class SerializationPerformanceTest {

    public static final int MAX_LOOP = 1000000;

    public static void main(String[] args) throws Exception {
        trySerialization();
        tryGson();
    }

    private static void tryGson() {
        long start = System.currentTimeMillis();
        Gson gson = new Gson();
        for (int i = 0; i < MAX_LOOP; i++) {
            String json = gson.toJson(createUser());
            gson.fromJson(json, User.class);
        }
        long end = System.currentTimeMillis();
        System.out.println("Gson cost: " + (end - start) + "ms");
    }

    private static void trySerialization() throws IOException, ClassNotFoundException {
        long start = System.currentTimeMillis();
        for (int i = 0; i < MAX_LOOP; i++) {
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            ObjectOutputStream stream = new ObjectOutputStream(byteStream);
            stream.writeObject(createUser());
            byte[] binary = byteStream.toByteArray();

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(binary);
            ObjectInputStream input = new ObjectInputStream(byteArrayInputStream);
            input.readObject();
        }
        long end = System.currentTimeMillis();
        System.out.println("Serialization cost: " + (end - start) + "ms");
    }

    private static User createUser() {
        User user = new User();
        user.setAaa(newValue());
        user.setBbb(newValue());
        user.setCcc(newValue());
        user.setDdd(newValue());
        user.setEee(newValue());
        user.setFff(newValue());
        user.setGgg(newValue());
        return user;
    }

    private static String newValue() {
        return "" + System.currentTimeMillis();
    }
}

作为java bean的类User

class User implements Serializable {
    private String aaa;
    private String bbb;
    private String ccc;
    private String ddd;
    private String eee;
    private String fff;
    private String ggg;

    String getAaa() {
        return aaa;
    }

    void setAaa(String aaa) {
        this.aaa = aaa;
    }

    String getBbb() {
        return bbb;
    }

    void setBbb(String bbb) {
        this.bbb = bbb;
    }

    String getCcc() {
        return ccc;
    }

    void setCcc(String ccc) {
        this.ccc = ccc;
    }

    String getDdd() {
        return ddd;
    }

    void setDdd(String ddd) {
        this.ddd = ddd;
    }

    String getEee() {
        return eee;
    }

    void setEee(String eee) {
        this.eee = eee;
    }

    String getFff() {
        return fff;
    }

    void setFff(String fff) {
        this.fff = fff;
    }

    String getGgg() {
        return ggg;
    }

    void setGgg(String ggg) {
        this.ggg = ggg;
    }
}

计算机中的结果:

Serialization cost: 12339ms
Gson cost: 3971ms

Gson版本比“序列化”版本快得多。为什么呢?!

我的测试代码有什么问题,或者Java内置序列化实际上是否很慢?

5 个答案:

答案 0 :(得分:5)

答案 1 :(得分:3)

可能是因为当类的实例首次写入流时,内置序列化会将类描述写入流中。编写单个 User对象,可以衡量User类描述构造和序列化+实例序列化的成本。在编写同一类的一系列对象时,内置序列化似乎更有效。

参考:http://docs.oracle.com/javase/7/docs/platform/serialization/spec/output.html#5552

答案 2 :(得分:2)

Java内置非编译测试中有很多对象创建,这可能是一个重要的开销。你可以尝试将new Gson()置于循环中并再次运行。我仍然希望Java内置函数更慢,因为它复制更多字节并创建比Gson更多的对象。

<强>更新

我在我的机器上使用无修改运行代码,结果发现Gson比Java内置序列化慢得多。

Serialization cost: 21163ms
Gson cost: 72636ms

答案 3 :(得分:2)

这是因为你将苹果与橙子进行比较。

在你的Gson测试中,你正在创建一个Gson实例并测量将N个对象序列化为它的时间。

在序列化测试中,您将测量创建N ObjectOutputStreams和N ObjectInputStreams的时间,并序列化一个对象。

尝试有效的比较。你可能会感到非常惊讶。

答案 4 :(得分:-1)

有点老帖子,但我发现的是做自己的本土方式更好。在附加图像中,创建模型对象的Native方式与Using Gson相比。每次Native方式结果都更好。 [尝试了27000个Json对象的27000个Json数组。]

            InputStream is = new FileInputStream(Zipper.extFile+"/airports.json");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, "UTF-8");
        ArrayList<Displayable> list = new ArrayList<>();
        Date d = new Date();
        long s = d.getTime();
        JSONArray jsonArray = new JSONArray(json);
        int len = jsonArray.length();
        for (int i=0;i<len;i++){
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Airport airport = new Airport();
            airport.setIata(jsonObject.optString("iata"));
            airport.setLon(jsonObject.optString("lon"));
            airport.setIso(jsonObject.optString("iso"));
            airport.setStatus(jsonObject.optInt("status"));
            airport.setContinent(jsonObject.optString("continent"));
            airport.setName(jsonObject.optString("name"));
            airport.setType(jsonObject.optString("type"));
            airport.setSize(jsonObject.optString("size"));
            airport.setLat(jsonObject.optString("lat"));
            list.add(airport);
        }
        Log.d("Time to build Java way","" + (new Date().getTime() - s));

        long s1 = d.getTime();
        Gson g = new Gson();
        List<? extends  Displayable> list1 = g.fromJson(json, new TypeToken<List<Airport>>(){}.getType());
        Log.d("Time to build Gson way","" + (new Date().getTime() - s1));

        Cache.getInstance().airportArrayList = list;

结果:

enter image description here