java序列化、hessian和protostuff性能比较

来源:互联网 发布:真维斯淘宝 编辑:程序博客网 时间:2024/06/06 03:01

序列化机制可以把对象转化成字节数组,将字节数组还原为对象称为反序列化。序列化常用于网络传输对象或存储对象,RPC(远程过程调用)函数调用的参数和结果就是通过序列化成字节数组传递的。

java内置的序列化能将实现了Serilazable接口的对象进行序列化和反序列化,ObjectOutputStream的writeObject()方法可序列化对象生成字节数组

ByteArrayOutputStream bytes = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(bytes);out.writeObject(obj);byte[] bytes = bytes.toByteArray();
ObjectInoputStream的readObject()方法可将字节数组还原成对象

ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));Object obj = in.readObject();
由于java内置的序列化工具性能不尽如人意,并且生成的字节数组较大、不能跨语言,出现了很多第三方序列化工具

Hessian是常用的第三方序列化工具,由于其简单高效特点而使用广泛。hessian序列化的使用方法和java内置的序列化差不多,需要对象实现Serilazable接口,然后调用Hessian的writeObject()方法,就可以生成字节数组

ByteArrayOutputStream bytes = new ByteArrayOutputStream();Hessian2Output out = new Hessian2Output(bytes);SerializerFactory serializerFactory = SerializerFactory.createDefault();out.setSerializerFactory(serializerFactory);out.writeObject(obj);out.close();        byte[] bytes = bytes.toByteArray();

Hessian2Input的readObject()方法可将字节数组还原成对象

Hessian2Input in = new Hessian2Input(new ByteArrayInputStream(bytes));SerializerFactory serializerFactory = SerializerFactory.createDefault();in.setSerializerFactory(serializerFactory);Object obj = in.readObject();in.close();
google开源的protobuf采用更为紧凑的二进制数组,表现更加优异,不过其使用方法极其繁琐,需要编写proto文件,然后使用protobuf的编译工具生成pojo类
protostuff基于protobuf的序列化,在运行只需要添加模式schema即可序列化对象,schema可由RuntimeSchema生成,然后调用ProtostuffIOUtil的toByteArray()方法

LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);Schema<T> schema = RuntimeSchema.createFrom(T.class);byte[] bytes = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
反序列化也需要添加模式schema,然后调用ProtostuffIOUtil的mergeFrom()方法即可将字节还原成对象
T obj = T.class.newInstance();Schema<T> schema = RuntimeSchema.createFrom(T.class);ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
下面对三种工具进行性能测试,对一个较大的对象BigPojo序列化和反序列化2000次
public static byte[] JavaSerialize(BigPojo obj) throws IOException//java内置序列化{ByteArrayOutputStream bytes = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(bytes);out.writeObject(obj);return bytes.toByteArray();}public static BigPojo JavaDeserialize(byte[] bytes) throws Exception//java内置反序列化{ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));return (BigPojo) in.readObject();}public static byte[] HessianSerialize(BigPojo obj) throws Exception//hessian序列化{ByteArrayOutputStream bytes = new ByteArrayOutputStream();Hessian2Output out = new Hessian2Output(bytes);SerializerFactory serializerFactory = SerializerFactory.createDefault();out.setSerializerFactory(serializerFactory);    out.writeObject(obj);    out.close();        return bytes.toByteArray();}public static BigPojo HessianDeserialize(byte[] bytes) throws Exception//hessian反序列化{Hessian2Input in = new Hessian2Input(new ByteArrayInputStream(bytes));SerializerFactory serializerFactory = SerializerFactory.createDefault();in.setSerializerFactory(serializerFactory);BigPojo obj = (BigPojo) in.readObject();in.close();    return obj;}public static byte[] ProtostuffSerialize(BigPojo obj)//protostuff序列化,已获得模式schema{LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);return ProtostuffIOUtil.toByteArray(obj, schema, buffer);}public static BigPojo ProtostuffDeserialize(byte[] bytes) throws Exception//protostuff反序列化{BigPojo obj = BigPojo.class.newInstance();ProtostuffIOUtil.mergeFrom(bytes, obj, schema);return obj;}
测试结果:
序列化时间 反序列化时间 总时间 字节数组大小
java:               64ms           109ms            173ms 308字节

hessian:        81ms          50ms              131ms  186字节

protostuff:     20ms           28ms               48ms    93字节
结果显示,在性能和生成字节数大小上,java内置的序列化工具最差,hessian稍好,protostuff最优


0 0