protobuf 还没看,所以暂时没有加入对比,但是已经默认是最快的序列化协议了。
测试点:
- 序列化时间
- 反序列化时间
- bytes大小
测试代码:
项目随便找一个pojo.我自己找的常见属性,没有严格测试到每一种数据类型。所以测试数据仅供自己学习。
package com.daojia.hessian;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class Person implements Serializable {
private static final long serialVersionUID = -1923645274767028479L;
private List address;
private Date brithday;
private boolean gender;
private double height;
private int id;
private String name;
private int phone;
private float weight;
public List getAddress() {
return address;
}
public void setAddress(List address) {
this.address = address;
}
public Date getBrithday() {
return brithday;
}
public void setBrithday(Date brithday) {
this.brithday = brithday;
}
public boolean isGender() {
return gender;
}
public void setGender(boolean gender) {
this.gender = gender;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
}
测试接口:
package com.daojia.hessian;
public interface TestCallback {
String getName();
byte[] writeObject(Object source);
Object readObject(byte[] bytes);
}
package com.daojia.hessian;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.HessianInput;
import com.caucho.hessian.io.HessianOutput;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.thoughtworks.xstream.XStream;
public class Test {
final static int testCount = 1000000;
public static void main(String[] args) {
// TODO Auto-generated method stub
// 序列化
testTemplate(new TestCallback() {
public String getName() {
return "Serializable Test";
}
@Override
public byte[] writeObject(Object source) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream output = new ObjectOutputStream(bout);
output.writeObject(source);
return bout.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public Object readObject(byte[] bytes) {
try {
ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
ObjectInputStream input = new ObjectInputStream(bin);
return input.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}, getPerson(), testCount);
// Xstream测试
final XStream xstream = new XStream();
testTemplate(new TestCallback() {
public String getName() {
return "Xstream test";
}
@Override
public byte[] writeObject(Object source) {
return xstream.toXML(source).getBytes();
}
@Override
public Object readObject(byte[] bytes) {
return xstream.fromXML(new ByteArrayInputStream(bytes));
}
}, getPerson(), testCount);
// json测试
testTemplate(new TestCallback() {
public String getName() {
return "fastJson Test";
}
@Override
public byte[] writeObject(Object source) {
try {
//String tmp =JSON.toJSONString(source);
//System.out.println(":"+tmp);
return JSON.toJSONString(source).getBytes();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object readObject(byte[] bytes) {
try {
//String tmp =new String(bytes);
//System.out.println("parse before:"+tmp);
JSONObject object = JSON.parseObject(new String(bytes));
return object;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}, getPerson(), testCount);
// json测试
final ObjectMapper objectMapper = new ObjectMapper();
// JSON configuration for compatibility
objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
testTemplate(new TestCallback() {
public String getName() {
return "Jackson Test";
}
@Override
public byte[] writeObject(Object source) {
try {
return objectMapper.writeValueAsBytes(source);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public Object readObject(byte[] bytes) {
try {
return objectMapper.readValue(bytes, 0, bytes.length, Person.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}, getPerson(), testCount);
// //hession
testTemplate(new TestCallback() {
public String getName() {
return "hessian 2 with no deflat";
}
@Override
public byte[] writeObject(Object source) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(bos);
// out.startMessage();
out.writeObject(source);
// out.completeMessage();
out.flush();
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public Object readObject(byte[] bytes) {
try {
ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
Hessian2Input in = new Hessian2Input(bin);
// in.startMessage();
Object obj = in.readObject();
// in.completeMessage();
return obj;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}, getPerson(), testCount);
// hessian 1 with no deflat
testTemplate(new TestCallback() {
public String getName() {
return "hessian 1 with no deflat";
}
@Override
public byte[] writeObject(Object source) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
HessianOutput out = new HessianOutput(bos);
out.writeObject(source);
out.flush();
return bos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object readObject(byte[] bytes) {
try {
ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
HessianInput in = new HessianInput(bin);
Object obj = in.readObject();
in.close();
return obj;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}, getPerson(), testCount);
}
private static void testTemplate(TestCallback callback, Object source, int count) {
int warmup = 10;
// 先进行预热,加载一些类,避免影响测试
for (int i = 0; i < warmup; i++) {
byte[] bytes = callback.writeObject(source);
callback.readObject(bytes);
}
restoreJvm(); // 进行GC回收
// 进行测试
long start = System.nanoTime();
long size = 0l;
for (int i = 0; i < count; i++) {
byte[] bytes = callback.writeObject(source);
// System.out.println("byte:"+bytes.toString());
size = size + bytes.length;
callback.readObject(bytes);
// System.out.println(callback.readObject(bytes));
bytes = null;
}
long nscost = (System.nanoTime() - start);
System.out.println(callback.getName() + " total cost=" + nscost + "ns , each cost="
+ (nscost / count) + "ns , and byte sizes = " + size / count);
restoreJvm();// 进行GC回收
}
private static void restoreJvm() {
// TODO Auto-generated method stub
int maxRestoreJvmLoops = 10;
long memUsedPrev = memoryUsed();
for (int i = 0; i < maxRestoreJvmLoops; i++) {
System.runFinalization();
System.gc();
long memUsedNow = memoryUsed();
// break early if have no more finalization and get constant mem used
if ((ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount() == 0)
&& (memUsedNow >= memUsedPrev)) {
break;
} else {
memUsedPrev = memUsedNow;
}
}
}
private static long memoryUsed() {
Runtime rt = Runtime.getRuntime();
return rt.totalMemory() - rt.freeMemory();
}
public byte[] writeObject(Object source) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(bos);
// out.startMessage();
out.writeObject(source);
// out.completeMessage();
out.flush();
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Object readObject(byte[] bytes) {
try {
ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
Hessian2Input in = new Hessian2Input(bin);
// in.startMessage();
Object obj = in.readObject();
// in.completeMessage();
return obj;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static Person getPerson() {
Person person = new Person();
List l = new ArrayList();
l.add("Beijing");
l.add("TaiWan");
person.setAddress(l);
person.setBrithday(new Date());
person.setGender(false);
person.setHeight(168.5D);
person.setId(300);
person.setName("Jack");
person.setPhone(188888888);
person.setWeight(55.2F);
return person;
}
}
测试demo网上找的demo,觉得挺好的,自己改造了下。
测试结果:
Serializable Test total cost=13418353185ns , each cost=13418ns , and byte sizes = 316
Xstream test total cost=30640534128ns , each cost=30640ns , and byte sizes = 325
fastJson Test total cost=2053259922ns , each cost=2053ns , and byte sizes = 142
Jackson Test total cost=2144118971ns , each cost=2144ns , and byte sizes = 142
hessian 2 with no deflat total cost=3356286519ns , each cost=3356ns , and byte sizes = 133
hessian 1 with no deflat total cost=11453543539ns , each cost=11453ns , and byte sizes = 169
可以看出:耗时上
fastJson < Jackson < hessian2 <hessian1 < jdk<xstream
fastjson比jackson快一点点,没那么显著,我觉得都可以。hessian2是慢了点。dubbox已经支持protobuf了。
测试版本: jdk 1.8
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.51</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.9.5</version>
</dependency>
参考:http://agapple.iteye.com/blog/859052