Java serialization options (1 of 4)

Java has plenty of serialization options. I tested some to see how well they’d serialize a class that represents a reading and how big it is.

I’m looking for some things: size of the final byte array, as this impacts network costs, speed of serialization/deserialization, compatibility with other systems and ease of development. This entry will look into the final size on wire. And there’s no way any text protocol is better than a binary one for size.

The class structure is below, without the verbose getter/setter). That class represents a device that is a 4-20 mA / 0-5V Analog to Digital Converter (ADC). This, by itself, is already a problem, as I don’t know if that input is a 4-20 or a 0-5. I’ll go back to this one and enable it to use JSR363, soon!

public class XSensoReading extends Measurement {
private Float analogInput1;
private Float analogInput2;
}

public abstract class Measurement implements Serializable {
public static enum Status {
UNKNOWN, OK, COULDNT_CONNECT, READ_TIMEOUT,
}
private ZonedDateTime timestamp = ZonedDateTime.now();
private Status status;
private String sourceId;
}

I’m testing 5 serialization methods:

  1. Java Serialization, the standard that comes with the JDK.
  2. Object.toString(), or just writing down your own serializer
  3. JSON using GSon  (other alternatives are available
  4. XML using Xstream (a good alternative would be JAX-B, if a bit less easy to use)
  5. Binary version Protobuf (a good alternative would be BSON)

There are other tools, surely, and other solutions to this problem, but those 5 are the ones I chose to begin with.

From a simple main class, we can see that getting this class into a wire and sending to my server can be a big problem or a small problem… I added Base64 representation so that it’s easy to copy and paste it around.

The most compact (Protobuf) is only 36 bytes long, while the most “verbose” (Java Serialization) is 584 bytes. That’s 16x more than the most compact!

This comes at a cost, which I’ll investigate in a next post.

At last, the code for this very simple test.

XSensoReading x = new XSensoReading();
x.setAnalogInput1(5.3f);
x.setAnalogInput2(297429f);
x.setStatus(Status.OK);
x.setTimestamp(ZonedDateTime.now());
x.setSourceId("xsenso1");

System.out.println(x);
XSensoReading [analogInput1=5.3, analogInput2=297429.0, toString()=Measurement [timestamp=2017-03-06T20:38:03.206-06:00[America/Chicago], status=OK, sourceId=xsenso1]]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos);
objectOutputStream.writeObject(x);
System.out.println("Java Serializable: " + baos.size());
System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
Java Serializable: 584
rO0ABXNyAD1tb2JpLnYyY29tLmNvbmVyYS5wcm90b2NvbC5sYW50cm9uaXgueHNlbnNvLmFwaS5YU2Vuc29SZWFkaW5nqK7NAkVGJeMCAAJMAAxhbmFsb2dJbnB1dDF0ABFMamF2YS9sYW5nL0Zsb2F0O0wADGFuYWxvZ0lucHV0MnEAfgABeHIAKG1vYmkudjJjb20uY29uZXJhLmRldmljZS5hcGkuTWVhc3VyZW1lbnQEUegedDhUxAIAA0wACHNvdXJjZUlkdAASTGphdmEvbGFuZy9TdHJpbmc7TAAGc3RhdHVzdAAxTG1vYmkvdjJjb20vY29uZXJhL2RldmljZS9hcGkvTWVhc3VyZW1lbnQkU3RhdHVzO0wACXRpbWVzdGFtcHQAGUxqYXZhL3RpbWUvWm9uZWREYXRlVGltZTt4cHQAB3hzZW5zbzF+cgAvbW9iaS52MmNvbS5jb25lcmEuZGV2aWNlLmFwaS5NZWFzdXJlbWVudCRTdGF0dXMAAAAAAAAAABIAAHhyAA5qYXZhLmxhbmcuRW51bQAAAAAAAAAAEgAAeHB0AAJPS3NyAA1qYXZhLnRpbWUuU2VylV2EuhsiSLIMAAB4cHchBgAAB+EDBhQmAwxHT4DoBwAPQW1lcmljYS9DaGljYWdveHNyAA9qYXZhLmxhbmcuRmxvYXTa7cmi2zzw7AIAAUYABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwQKmZmnNxAH4ADkiROqA=
baos.reset();
baos.write(x.toString().getBytes("UTF-8"));
System.out.println("Java toString(): " + baos.size());
System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
Java toString(): 167
WFNlbnNvUmVhZGluZyBbYW5hbG9nSW5wdXQxPTUuMywgYW5hbG9nSW5wdXQyPTI5NzQyOS4wLCB0b1N0cmluZygpPU1lYXN1cmVtZW50IFt0aW1lc3RhbXA9MjAxNy0wMy0wNlQyMDozODowMy4yMDYtMDY6MDBbQW1lcmljYS9DaGljYWdvXSwgc3RhdHVzPU9LLCBzb3VyY2VJZD14c2Vuc28xXV0=
baos.reset();
Gson gson = new Gson();
PrintWriter pw = new PrintWriter(baos);
gson.toJson(x, pw);
pw.flush();
System.out.println("GSon toJson(): " + baos.size());
System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
GSon toJson(): 269
eyJhbmFsb2dJbnB1dDEiOjUuMywiYW5hbG9nSW5wdXQyIjoyOTc0MjkuMCwidGltZXN0YW1wIjp7ImRhdGVUaW1lIjp7ImRhdGUiOnsieWVhciI6MjAxNywibW9udGgiOjMsImRheSI6Nn0sInRpbWUiOnsiaG91ciI6MjAsIm1pbnV0ZSI6MzgsInNlY29uZCI6MywibmFubyI6MjA2MDAwMDAwfX0sIm9mZnNldCI6eyJ0b3RhbFNlY29uZHMiOi0yMTYwMH0sInpvbmUiOnsiaWQiOiJBbWVyaWNhL0NoaWNhZ28ifX0sInN0YXR1cyI6Ik9LIiwic291cmNlSWQiOiJ4c2Vuc28xIn0=
baos.reset();
XStream xstream = new XStream();
xstream.toXML(x, baos);
System.out.println("XStream toXML(): " + baos.size());
System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
XStream toXML(): 322
PG1vYmkudjJjb20uY29uZXJhLnByb3RvY29sLmxhbnRyb25peC54c2Vuc28uYXBpLlhTZW5zb1JlYWRpbmc+CiAgPGFuYWxvZ0lucHV0MT41LjM8L2FuYWxvZ0lucHV0MT4KICA8YW5hbG9nSW5wdXQyPjI5NzQyOS4wPC9hbmFsb2dJbnB1dDI+CiAgPHRpbWVzdGFtcCByZXNvbHZlcy10bz0iamF2YS50aW1lLlNlciIgc2VyaWFsaXphdGlvbj0iY3VzdG9tIi8+CiAgPHN0YXR1cz5PSzwvc3RhdHVzPgogIDxzb3VyY2VJZD54c2Vuc28xPC9zb3VyY2VJZD4KPC9tb2JpLnYyY29tLmNvbmVyYS5wcm90b2NvbC5sYW50cm9uaXgueHNlbnNvLmFwaS5YU2Vuc29SZWFkaW5nPg==
XSensoReadingProto.XSensoReading protoReading = XSensoReadingProto.XSensoReading.newBuilder()
.setAnalogInput1(x.getAnalogInput1()).setAnalogInput2(x.getAnalogInput2())
.setTimestamp(x.getTimestamp().toEpochSecond()*1000).setStatus(XSensoReadingProto.XSensoReading.Status.valueOf(x.getStatus().ordinal()))
.setSource(x.getSourceId())
.build();
byte[] contents = protoReading.toByteArray();
System.out.println("Protobuffers: " + contents.length);
System.out.println(Base64.getEncoder().encodeToString(contents));
Protobuffers: 36
CPjlhbWqKxEAAABAMzMVQBkAAAAAVCcSQSABKgd4c2Vuc28x
Advertisements

One thought on “Java serialization options (1 of 4)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s