Freewind
Freewind

Reputation: 198238

Why java built-in serialization is worse than Gson?

I thought the performance of Java built-in serialization should be good. Compare to Gson, it doesn't need to do the lexical analysis, it should be faster than Gson.

But in my test, the result is just the opposite. See my code:

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();
    }
}

The class User which is a java bean:

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;
    }
}

The result in my computer:

Serialization cost: 12339ms
Gson cost: 3971ms

The Gson version is much faster than the "Serialization" one. Why?!

Is there anything wrong is my test code, or Java built-in serialization is actually slow?

Upvotes: 1

Views: 3345

Answers (5)

Itzdsp
Itzdsp

Reputation: 912

Bit old post, but what i find is Native way of doing yourself is better. In the attached image, Native way of creating the model objects vs Using Gson. Every time Native way result was better. [Tried with 27000 Json array of 27000 Json objects.]

            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;

Result:

enter image description here

Upvotes: -1

user207421
user207421

Reputation: 310916

It it because you're comparing apples with oranges.

In your Gson test, you are creating a single Gson instance and measuring the time to serialize N objects to it.

In your Serialization test, you are measuring the time to create N ObjectOutputStreams and N ObjectInputStreams, and serialize one object.

Try a valid comparison. You might get quite a surprise.

Upvotes: 3

leventov
leventov

Reputation: 15283

Probably because built-in serialization writes class description into the stream, when an instance of the class is first written into the stream. Writing a single User object, you measure the cost of User class description construction and serialization + an instance serialization. Built-in serialization should seem more efficient on writing series of objects of the same class.

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

Upvotes: 3

gigadot
gigadot

Reputation: 8969

There are a lot of object creations in the test for Java built-inserialization and that is probably a significant overhead. Can you try to put new Gson() inside the loop and run again. I still expect the Java built-in function to be slower because it copies more bytes and creates more objects than Gson.

Update

I ran your code with no modification on my machine and it turns out that Gson is much slower than Java built-in serialization.

Serialization cost: 21163ms
Gson cost: 72636ms

Upvotes: 2

Matt Ball
Matt Ball

Reputation: 359816

Java built-in serialization is quite slow. For reference: https://github.com/eishay/jvm-serializers/wiki

However, there are quite a few ways in which your benchmark should be improved for more-accurate results.

Upvotes: 5

Related Questions