ToB企服应用市场:ToB评测及商务社交产业平台

标题: Kryo深拷贝工具 [打印本页]

作者: 大号在练葵花宝典    时间: 2024-12-14 04:52
标题: Kryo深拷贝工具
优质博文:IT-BLOG-CN
一、工具介绍

Kryo 是一个快速高效的 Java 二进制对象图序列化框架。 该项目标目标是高速、小尺寸和易于利用的 API。 该项目在需要持久化对象的任何时候都很有效,无论是文件、数据库照旧通过网络。
github地点:https://github.com/EsotericSoftware/kryo
二、利用方法

1 引入kryo工具依赖
  1. <dependency>
  2.     <groupId>com.esotericsoftware</groupId>
  3.     <artifactId>kryo</artifactId>
  4.     <version>5.3.0</version>
  5. </dependency>
复制代码
2 快速开始
利用下面的代码,可以简朴举行对象的深拷贝
  1. public static <T> T kryoCopy(T origin) {
  2.     Kryo kryo = new Kryo();
  3.     kryo.setRegistrationRequired(false);
  4.     return kryo.copy(origin);
  5. }
复制代码
利用下面的代码,可以简朴举行对象序列化和反序列化
  1. public static <T> Output kryoSerialize(T origin) {
  2.     Kryo kryo = new Kryo();
  3.     Output output = new Output();
  4.    kryo.setRegistrationRequired(false);
  5.     kryo.writeObject(output, origin);
  6.    return output;
  7. }
  8. public static <T> T kryoDeserialize(Input input, Class<T> clazz) {
  9.     try {
  10.         return kryo.readObject(input, clazz);
  11.     } catch (Exception e) {
  12.         log.error("Deserialize Error", e);
  13.         return null;
  14.     }
  15. }
复制代码
三、相关设置

3.1 通用设置
Kryo在拷贝对象前需要先对该类举行注册,包括该对象中利用到的其他类,注册后的对象拷贝速率更快。
  1. kryo.register(T.class);
复制代码
对于复杂对象,或是其他无法注册完全的对象,可以用以下代码跳过注册
  1. kryo.setRegistrationRequired(false);
复制代码
Kryo提供了许多序列化器供利用,每个都有各自的作用,具体可以看github上的文档。Kryo利用注册的方式支持对于差别的类利用差别的序列化器。如下所示:
  1. kryo.register(T.class, new FieldSerializer<>(kryo, T.class));
  2. kryo.register(R.class, new TaggedFieldSerializer<>(kryo, R.class));
复制代码
3.2 FieldSerializer
FieldSerializer对于拷贝的设置如下所示:
设置项描述默认值copyTransient如果为true,那么transient修饰字段也会被拷贝true可以通过FieldSerializerFactory修改设置,利用方法如下:
  1. SerializerFactory.FieldSerializerFactory serializerFactory = new SerializerFactory.FieldSerializerFactory();
  2. serializerFactory.getConfig().setCopyTransient(false);
  3. kryo.setDefaultSerializer(serializerFactory);
复制代码
3.3 TaggedFieldSerializer
TaggedFieldSerializer继承FieldSerializer,对于拷贝无额外设置项。同样可以通过TaggedFieldSerializerFactory修改设置,利用方法如下:
  1. SerializerFactory.TaggedFieldSerializerFactory tagSerializerFactory = new SerializerFactory.TaggedFieldSerializerFactory();
  2. tagSerializerFactory.getConfig().setCopyTransient(false);
  3. kryo.setDefaultSerializer(serializerFactory);
复制代码
四、并发处置惩罚

Kryo提供Pool类用于并发处置惩罚,利用过程中需要先创建Kryo池,池的容量表示用于存储的最大对象数,但是同时获取的数量可以超过池的最大容量:
  1. // 构造器参数分别为thread safe, soft references, maximum capacity
  2. Pool<Kryo> KRYO_POOL = new Pool<Kryo>(true, false, 64) {
  3.     @Override
  4.     protected Kryo create() {
  5.         Kryo kryo = new Kryo();
  6.         // 配置Kryo
  7.         return kryo;
  8.     }
  9. };
复制代码
然后在利用时先从Pool中获取Kryo对象,并在完成拷贝后(无论是否乐成)务必归还:
  1. Kryo kryo = KRYO_POOL.obtain();
  2. try {
  3.     return kryo.copy(origin);
  4. } catch (Exception e) {
  5.     log.error("Deep Copy", e);
  6.     throw new RuntimeException("kryo copy fail!", e);
  7. } finally {
  8.     // 一定要归还
  9.     KRYO_POOL.free(kryo);
  10. }处理序列化对象时,可以创建一个Pool中的泛型类改为Output的池
复制代码
五、性能测试

深拷贝

1.1 JMH性能对比
分别对Hotel对象(0)、小ListSearchResponse对象(1)、大ListSearchResponse对象(2)举行了多轮深拷贝测试。
JMH设置为单线程、迭代10次取平均值,具体如下所示:
  1. @BenchmarkMode(Mode.AverageTime)
  2. @Warmup(iterations = 3, time = 1)
  3. @Measurement(iterations = 10, time = 5)
  4. @Fork(1)
  5. @State(value = Scope.Benchmark)
  6. @OutputTimeUnit(TimeUnit.NANOSECONDS)
复制代码
每次迭代需要循环1000次多轮拷贝。
测试结果如下图所示,其中testCopy是用ProtostuffSerializer举行序列化,反序列化来深拷贝。从结果可以发现,Kryo的深拷贝时间相较于ProtostuffSerializer平均缩短了50-60%。

1.2 线上性能对比
左图为深拷贝平均耗时(单位毫秒),右图为kryo相较于protostuff的变化幅度,可以发现kryo平均缩短了30-40%的拷贝时间

序列化

测试对象与深拷贝测试中的雷同,分别测试了Protostuff序列化、Kryo序列化、以及他们各自加上zstd压缩的序列化性能
2.1 序列化
下图是序列化性能测试结果,可以发现Kryo序列性能更好,对象越大,Kryo优势就更明显

2.2 反序列化
下图是序列化+反序列化性能测试结果,可以发现Kryo序列性能更好,对象越大,Kryo优势就更明显



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4