大号在练葵花宝典 发表于 2024-12-14 04:52:27

Kryo深拷贝工具

优质博文:IT-BLOG-CN
一、工具介绍

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

1 引入kryo工具依赖
<dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>kryo</artifactId>
    <version>5.3.0</version>
</dependency>
2 快速开始
利用下面的代码,可以简朴举行对象的深拷贝
public static <T> T kryoCopy(T origin) {
    Kryo kryo = new Kryo();
    kryo.setRegistrationRequired(false);

    return kryo.copy(origin);
}
利用下面的代码,可以简朴举行对象序列化和反序列化
public static <T> Output kryoSerialize(T origin) {
    Kryo kryo = new Kryo();
    Output output = new Output();
   kryo.setRegistrationRequired(false);

    kryo.writeObject(output, origin);
   return output;
}
public static <T> T kryoDeserialize(Input input, Class<T> clazz) {
    try {
      return kryo.readObject(input, clazz);
    } catch (Exception e) {
      log.error("Deserialize Error", e);
      return null;
    }
}
三、相关设置

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

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

深拷贝

1.1 JMH性能对比
分别对Hotel对象(0)、小ListSearchResponse对象(1)、大ListSearchResponse对象(2)举行了多轮深拷贝测试。
JMH设置为单线程、迭代10次取平均值,具体如下所示:
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 3, time = 1)
@Measurement(iterations = 10, time = 5)
@Fork(1)
@State(value = Scope.Benchmark)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
每次迭代需要循环1000次多轮拷贝。
测试结果如下图所示,其中testCopy是用ProtostuffSerializer举行序列化,反序列化来深拷贝。从结果可以发现,Kryo的深拷贝时间相较于ProtostuffSerializer平均缩短了50-60%。
https://i-blog.csdnimg.cn/direct/7319b89b1d7b43bd8b12379d627a9193.png
1.2 线上性能对比
左图为深拷贝平均耗时(单位毫秒),右图为kryo相较于protostuff的变化幅度,可以发现kryo平均缩短了30-40%的拷贝时间
https://i-blog.csdnimg.cn/direct/1035aa4040c348f8894b55d2aacf5268.png
序列化

测试对象与深拷贝测试中的雷同,分别测试了Protostuff序列化、Kryo序列化、以及他们各自加上zstd压缩的序列化性能
2.1 序列化
下图是序列化性能测试结果,可以发现Kryo序列性能更好,对象越大,Kryo优势就更明显
https://i-blog.csdnimg.cn/direct/f0133da1266c4b6fba5d22640bd665b5.png
2.2 反序列化
下图是序列化+反序列化性能测试结果,可以发现Kryo序列性能更好,对象越大,Kryo优势就更明显
https://i-blog.csdnimg.cn/direct/c6214f0129a74985b16fbd7424fd642b.png
https://i-blog.csdnimg.cn/direct/c6d29579caf34c99aa078a5195f3d155.png

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