jackson、fastjson、kryo、protostuff等序列化工具性能对比
简介
实际项目中,我们经常需要使用序列化工具来存储和传输对象。目前用得比较多的序列化工具有:jackson、fastjson、kryo、protostuff、fst 等,本文将简单对比这几款工具序列化和反序列化的性能。
项目环境
本文使用 jmh 作为测试工具。
os:win 10
jdk:1.8.0_231
jmh:1.25
选择的序列化工具及对应的版本如下:
fastjson:1.2.74
jackson:2.11.3
kryo:5.0.0
fst:2.57
protostuff:1.7.2
测试代码
为了公平,我尽量让测试用例中对序列化工具的用法更贴近实际项目,例如,kryo 的Kryo对象不是线程安全的,实际项目中我们并不会每次使用就直接 new 一个新对象,而是使用 ThreadLocal 或者池来减少创建对象的开销。
本文使用的 java bean 如下。一个用户对象,一对一关联部门对象和岗位对象,其中部门对象又存在自关联。
public class User implements Serializable {
private static final long serialVersionUID = 1L;
// 普通属性--29个
private String id;
private String account;
private String password;
private Integer status;
// ······
/**
* 所属部门
*/
private Department department;
/**
* 岗位
*/
private Position position;
// 以下省略setter/getter方法
}
public class Department implements Serializable {
private static final long serialVersionUID = 1L;
// 普通属性--7个
private String id;
private String parentId;
// ······
/**
* 子部门
*/
private List<Department> children;
// 以下省略setter/getter方法
}
public class Position implements Serializable {
private static final long serialVersionUID = 1L;
// 普通属性--6个
private String id;
private String name;
// ······
// 以下省略setter/getter方法
}
下面展示部分测试代码,完整代码见末尾链接。
JDK 自带的序列化工具
JDK 提供了ObjectOutputStream用于支持序列化,ObjectInputStream用于反序列化。注意,使用 JDK 自带的序列化工具时,java bean 必须实现Serializable,否则会抛出NotSerializableException异常 。使用关键字 transient 修饰的成员属性不会被序列化。
// 序列化
@Benchmark
public byte[] jdkSerialize(CommonState commonState) throws Exception {
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(byteArray);
outputStream.writeObject(commonState.user);
outputStream.flush();
outputStream.close();
return byteArray.toByteArray();
}
// 反序列化
@Benchmark
public User jdkDeSerialize(JdkState jdkState) throws Exception {
ByteArrayInputStream byteArray = new ByteArrayInputStream(jdkState.bytes);
ObjectInputStream inputStream = new ObjectInputStream(byteArray);
User user = (User)inputStream.readObject();
inputStream.close();
assert "zzs0".equals(user.getName());
return user;
}
fastjson
fastjson 由阿里团队开发,是目前最快的Java 实现的 json 库。 fastjson 的 API 非常简洁,并且支持一定程度的定制(例如,注解 @JSONField、枚举Feature等定制序列化)。被人诟病的,可能是 fastjson 的 bug 比较多。
// 序列化
@Benchmark
public byte[] fastJsonSerialize(CommonState commonState) {
return JSON.toJSONBytes(commonState.user);
}
// 反序列化
@Benchmark
public User fastJsonDeSerialize(FastJsonState fastJsonState) {
User user = JSON.parseObject(fastJsonState.bytes, User.class);
assert "zzs0".equals(user.getName());
return user;
}
jackson
jackson 由 fasterxml 组织开发,相比 fastjson,有着更强大的功能、更高的稳定性、更好的扩展性、更丰富的定制支持。Spring 默认使用的 json 解析工具就是 jackson。
使用 jackson 需要注意,ObjectMapper对象是线程安全的,可以重复使用。
// 序列化
@Benchmark
public byte[] jacksonSerialize(CommonState commonState, JacksonState jacksonState) throws Exception {
return jacksonState.objectMapper.writeValueAsBytes(commonState.user);
}
// 反序列化
@Benchmark
public User jacksonDeSerialize(JacksonState jacksonState) throws Exception {
User user = jacksonState.objectMapper.readValue(jacksonState.bytes, User.class);
assert "zzs0".equals(user.getName());
return user;
}
kryo
kryo 由 EsotericSoftware 组织开发,不兼容 jdk 自带序列化工具的数据,kryo 序列化后的数据要更小,至于 API 的简洁性方面,我觉得还是差了一些,一不小心就会采坑。使用 kryo 需要注意以下几点:
Kryo对象不是线程安全的,可以使用ThreadLocal或池来获取(本文使用池获取);- kryo 通过类注册可以在序列化数据中写入类的 class id,而不是类的全限定类名,从而减小序列化数据的大小。但是,我们很难保证同样的类在不同的机器上注册的 class id,所以,建议设置
kryo.setRegistrationRequired(false);,因为同样的 Class 在不同的机器上注册编号很难保证一致; - 当 java bean 出现循环引用时,使用 kryo 可能会出现栈内存溢出,这个时候可以通过设置
kryo.setReferences(true);来避免。如果项目中不可能出现循环引用,则可以设置为 false 以提高性能。
// 序列化
@Benchmark
public byte[] kryoSerialize(CommonState commonState, KryoState kryoState) {
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
Output output = new Output(byteArray);
Kryo kryo = kryoState.kryoPool.obtain();
kryo.writeClassAndObject(output, commonState.user);
kryoState.kryoPool.free(kryo);
output.flush();
output.close();
return byteArray.toByteArray();
}
//反序列化
@Benchmark
public User kryoDeSerialize(KryoState kryoState) throws Exception {
ByteArrayInputStream byteArray = new ByteArrayInputStream(kryoState.bytes);
Input input = new Input(byteArray);
Kryo kryo = kryoState.kryoPool.obtain();
User user = (User)kryo.readClassAndObject(input);
kryoState.kryoPool.free(kryo);
input.close();
assert "zzs0".equals(user.getName());
return user;
}
fst
fst(fast-serialization)是由 RuedigerMoeller 开发,API 非常简洁。使用时需要注意,FSTConfiguration对象可以重复使用。
其实,fst 也支持以 json 形式序列化,但是这一块的性能稍差而且用的人较少,这里就不提及了。
// 序列化
@Benchmark
public byte[] fstSerialize(CommonState commonState, FSTConfigurationState fSTConfigurationState) {
return fSTConfigurationState.fSTConfiguration.asByteArray(commonState.user);
}
// 反序列化
@Benchmark
public User fstDeSerialize(FSTState fstState) throws Exception {
User user = (User)fstState.fSTConfiguration.asObject(fstState.bytes);
assert "zzs0".equals(user.getName());
return user;
}
protostuff
protostuff 是基于 google protobuf 开发而来(与 protobuf 相比,protostuff 在几乎不损耗性能的情况下做到了不用写.proto文件来实现序列化),不兼容 jdk 自带序列化工具的数据,序列化后的数据要更小。使用 protostuff 需要注意几点:
- protostuff 使用字段的定义顺序作为字段的 tag,新增字段时必须保证原字段顺序不变,否则旧数据可能会反序列化失败;
- protostuff 不能直接序列化 Array、List、Map,如果需要序列化,需要先包装成 java bean;
// 序列化
@Benchmark
public byte[] protostuffSerialize(CommonState commonStateme) {
Schema<User> schema = (Schema<User>)RuntimeSchema.getSchema(User.class);
return ProtostuffIOUtil.toByteArray(commonStateme.user, schema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
}
// 反序列化
@Benchmark
public User protostuffDeSerialize(ProtostuffState protostuffState) throws Exception {
User user = new User();
Schema<User> schema = (Schema<User>)RuntimeSchema.getSchema(User.class);
ProtostuffIOUtil.mergeFrom(protostuffState.bytes, user, schema);
assert "zzs0".equals(user.getName());
return user;
}
测试结果
以下以吞吐量作为指标,相同条件下,吞吐量越大越好。
序列化
cmd 指令如下:
mvn clean package
java -ea -jar target/benchmarks.jar cn.zzs.serialize.SerializeTest -f 1 -t 1 -wi 10 -i 10
测试结果:
# JMH version: 1.25
# VM version: JDK 1.8.0_231, Java HotSpot(TM) 64-Bit Server VM, 25.231-b11
# VM invoker: D:\growUp\installation\jdk1.8.0_231\jre\bin\java.exe
# VM options: -ea
# Warmup: 10 iterations, 10 s each
# Measurement: 10 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
Benchmark Mode Cnt Score Error Units
SerializeTest.fastJsonSerialize thrpt 10 449.474 ± 1.851 ops/ms
SerializeTest.fstSerialize thrpt 10 694.716 ± 7.240 ops/ms
SerializeTest.jacksonSerialize thrpt 10 330.610 ± 6.968 ops/ms
SerializeTest.jdkSerialize thrpt 10 132.483 ± 0.379 ops/ms
SerializeTest.kryoSerialize thrpt 10 609.969 ± 3.288 ops/ms
SerializeTest.protostuffSerialize thrpt 10 762.737 ± 10.918 ops/ms
可以看到,序列化速度方面:protostuff > fst > kryo > fastjson > jackson > jdk。
反序列化
cmd 指令如下:
mvn clean package
java -ea -jar target/benchmarks.jar cn.zzs.serialize.DeSerializeTest -f 1 -t 1 -wi 10 -i 10
测试结果:
# JMH version: 1.25
# VM version: JDK 1.8.0_231, Java HotSpot(TM) 64-Bit Server VM, 25.231-b11
# VM invoker: D:\growUp\installation\jdk1.8.0_231\jre\bin\java.exe
# VM options: -ea
# Warmup: 10 iterations, 10 s each
# Measurement: 10 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
fastjson serialized data size:1044
fst serialized data size:607
jackson serialized data size:1060
jdk serialized data size:1700
kryo serialized data size:597
protostuff serialized data size:543
Benchmark Mode Cnt Score Error Units
DeSerializeTest.fastJsonDeSerialize thrpt 10 397.069 ± 3.507 ops/ms
DeSerializeTest.fstDeSerialize thrpt 10 465.813 ± 4.700 ops/ms
DeSerializeTest.jacksonDeSerialize thrpt 10 226.412 ± 1.436 ops/ms
DeSerializeTest.jdkDeSerialize thrpt 10 27.919 ± 0.352 ops/ms
DeSerializeTest.kryoDeSerialize thrpt 10 448.978 ± 3.504 ops/ms
DeSerializeTest.protostuffDeSerialize thrpt 10 499.328 ± 4.485 ops/ms
可以看到,反序列化速度方面:protostuff > fst > kryo > fastjson > jackson > jdk,该结果和序列化一致。
序列化数据的大小方面:protostuff < kryo < fst < fastjson < jackson < jdk。
以上数据仅供参考。感谢阅读。
相关源码请移步:serialize-tool-demo
本文为原创文章,转载请附上原文出处链接:https://www.cnblogs.com/ZhangZiSheng001/p/13948414.html
jackson、fastjson、kryo、protostuff等序列化工具性能对比的更多相关文章
- [java]序列化框架性能对比(kryo、hessian、java、protostuff)
序列化框架性能对比(kryo.hessian.java.protostuff) 简介: 优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Pro ...
- 序列化框架性能对比(kryo、hessian、java、protostuff)
简介: 优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Protostuff 速度快,基于protobuf 需静态编译 Protostuff- ...
- java序列化框架(protobuf、thrift、kryo、fst、fastjson、Jackson、gson、hessian)性能对比
我们为什么要序列化 举个栗子:下雨天我们要打伞,但是之后我们要把伞折叠起来,方便我们存放.那么运用到我们java中道理是一样的,我们要将数据分解成字节流,以便存储在文件中或在网络上传输,这叫序列 ...
- json工具性能比较:json-lib和jackson进行Java对象到json字符串序列化[转]
网上查找“java json”,发现大家使用最多的还是json-lib来进行java对象的序列化成json对象和反序列化成java对象的操作.但是之前在网上也看到过一往篇关于json序列化性能比较的文 ...
- Jackson和fastjson简单用法及性能对比
背景: Java处理JSON数据有三个比较流行的类库FastJSON.Gson和Jackson.fastjson是阿里做的国有开源Java工具包,jackson是spring mvc内置的json转换 ...
- spring-data-redis注册fastjson序列化工具
使用spring-data-redis的时候,其序列化工具自带:
- 网络传输数据序列化工具Protostuff
一直在物色比较好用的网络传输数据序列化工具,看了诸如marshalling,protobuff等,但是均有一个共同特点,使用起来异常繁杂,有没有比较好用同时性能又不会太差的组件呢?答案当然是有的,那就 ...
- FastJson实现复杂对象序列化与反序列化
原文:http://blog.csdn.net/xqhadoop/article/details/62217954 一.认识FastJson 1.优势 fastjson是目前java语言中最快的jso ...
- Dubbo + Kryo 实现高速序列化
Dubbo 中的序列化 Dubbo RPC 是 Dubbo 体系中最核心的一种高性能.高吞吐量的远程调用方式,可以称之为多路复用的 TCP 长连接调用: 长连接:避免了每次调用新建 TCP 连接,提高 ...
随机推荐
- 074 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 06 综合案例-数组移位-主方法功能3的实现
074 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 06 综合案例-数组移位-主方法功能3的实现 本文知识点:综合案例-数组移位-主方法功能3的实现 说明:因为 ...
- java安全编码指南之:输入注入injection
目录 简介 SQL注入 java中的SQL注入 使用PreparedStatement XML中的SQL注入 XML注入的java代码 简介 注入问题是安全中一个非常常见的问题,今天我们来探讨一下ja ...
- 多测师讲解python _类(原始版)_高级讲师肖sir
# Python中的类: '''定义一个类:class +名称=类 在类当中定义:def +名称=实例方法(self)与类平齐def +名称=普通函数定义一个函数:def +名称=函数在函数中:函数( ...
- day20 Pyhton学习 面向对象-成员
一.类的成员 class 类名: # 方法 def __init__(self, 参数1, 参数2....): # 属性变量 self.属性1 = 参数1 self.属性2 = 参数2 .... # ...
- bootStrap小结2
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...
- abp(net core)+easyui+efcore实现仓储管理系统——出库管理之三(五十一)
abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...
- 圆形进度条的模仿1-DrawArc,DrawCircle,DrawText讲解
1:画弧 canvas.drawArc(oval,startAngle,sweepAngle,useCenter,paint) 第一个参数:绘制的区域,oval可以是被定好了的一个区域,也可以将ova ...
- 【应用服务 App Service】当遇见某些域名在Azure App Service中无法解析的错误,可以通过设置指定DNS解析服务器来解决
问题情形 当访问部署在Azure App Service中的应用返回 "The remote name could not be resolved: ''xxxxxx.com'" ...
- Linux文件元数据和节点表结构
文件元数据 一块硬盘的分区可以认为有两部分组成,保存元数据的成为节点表,用来保存属性等. 元数据中有个小指针,指向数据存放的实际空间. 元数据(Metadata) 又称中介数据.中继数据,为描述数据的 ...
- Flutter Webview添加Cookie的正确姿势
场景 h5页面要从cookie里面取数据,所以需要在flutter webview的cookie里面塞一些数据,设置的数据多达十几条:按照网上查的使用方式来设置,通过fiddler抓包发现,只能生效一 ...