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

序列化机制可以把对象转化成字节数组,将字节数组还原为对象称为反序列化。序列化常用于网络传输对象或存储对象,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 schema = RuntimeSchema.createFrom(T.class);		
byte[] bytes = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
反序列化也需要添加模式schema,然后调用ProtostuffIOUtil的mergeFrom()方法即可将字节还原成对象
T obj = T.class.newInstance();
Schema 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最优


你可能感兴趣的:(java)