kryo优缺点

Kryo序列化优点

其实之前在“Kryo序列化生效位置”处已经提到了Kryo序列化的优点,这里总结一下,大致为: 
1. 算子函数中使用到的外部变量,使用Kryo以后:优化网络传输的性能,可以优化集群中内存的占用和消耗; 
2. 持久化RDD,优化内存的占用和消耗,持久化RDD占用的内存越少,task执行的时候,创建的对象,就不至于频繁的占满内存,频繁发生GC; 
3、shuffle:可以优化网络传输的性能。


Kryo序列化机制比默认的Java序列化机制速度要快,序列化后的数据要更小,大概是Java序列化机制的1/10。所以Kryo序列化优化以后,可以让网络传输的数据变少,在集群中耗费的内存资源大大减少。


这句话引用oschina对Kryo的解释:Kryo 是一个快速高效的Java对象图形序列化框架,主要特点是性能、高效和易用。该项目用来序列化对象到文件、数据库或者网 络。

     但是,它也有一个致命的弱点:生成的byte数据中部包含field数据,对类升级的兼容性很差!所以,若用kryo序列化对象用于C/S架构的话,两边的Class结构要保持一致。

kryo
使用kryo默认的序列化方式fieldSerializer,
对需要序列化的对象采取默认的操作。开启reference,关闭register


       Kryo在类注册且reference关闭的情况下,序列化速度和大小明显 优于hessianjava,接近于protostuff。开启reference后将序列化速度将明显变慢,但仍旧优于hessian

相关知识:

         类注册:将需要序列化的类注册到kryo中,可以提高序列化与反序列化的速度。

         Reference:开启这个选项后,相同的对象将被序列化为同一个byte[],默认关闭,如果要支持循环引用,则必须开启


稳定性测试:

    测试用例(见附件)

         循环引用:Cyclic.java

序列化方式

无默认构造函数

循环引用

对象为null

是否需要预先知道对象所属的类

大对象(4M)

Kryo

支持

需将reference选项打开

支持

不需要,关闭register

支持

Java

支持

支持

支持

不需要

支持

Protostuff

支持

支持

支持

不需要

支持

Protostuff

-runtime

不支持

支持

支持

需要

支持

Hessian

支持

支持

支持

不需要

支持

序列化框架性能对比(kryo、hessian、java、protostuff)

简介:

 

优点

缺点

Kryo

速度快,序列化后体积小

跨语言支持较复杂

Hessian

默认支持跨语言

较慢

Protostuff

速度快,基于protobuf

需静态编译

Protostuff-Runtime

无需静态编译,但序列化前需预先传入schema

不支持无默认构造函数的类,反序列化时需用户自己初始化序列化后的对象,其只负责将该对象进行赋值

Java

使用方便,可序列化所有类

速度慢,占空间


Kryo 是一个快速高效的Java对象图形序列化框架,它原生支持java,且在java的序列化上甚至优于google著名的序列化框架protobuf。由于protobuf需要编写Schema文件(.proto),且需静态编译。故选择与Kryo类似的序列化框架Hessian作为比较来了解一下Kryo为什么这么快。

序列化的过程中主要有3个指标:

1、对象序列化后的大小

一个对象会被序列化工具序列化为一串byte数组,这其中包含了对象的field值以及元数据信息,使其可以被反序列化回一个对象

2、序列化与反序列化的速度

一个对象被序列化成byte数组的时间取决于它生成/解析byte数组的方法

3、序列化工具本身的速度

序列化工具本身创建会有一定的消耗。


从序列化后的字节可以看出以下几点:

1、Kryo序列化后比Hessian小很多。(kryo优于hessian)

2、由于Kryo没有将类field的描述信息序列化,所以Kryo需要以自己加载该类的filed。这意味着如果该类没有在kryo中注册,或者该类是第一次被kryo序列化时,kryo需要时间去加载该类(hessian优于kryo)

3、由于2的原因,如果该类已经被kryo加载过,那么kryo保存了其类的信息,就可以很快的将byte数组填入到类的field中,而hessian则需要解析序列化后的byte数组中的field信息,对于序列化过的类,kryo优于hessian。

4、hessian使用了固定长度存储int和long,而kryo则使用的变长,实际中,很大的数据不会经常出现。(kryo优于hessian)

5、hessian将序列化的字段长度写入来确定一段field的结束,而kryo对于String将其最后一位byte+x70用于标识结束(kryo优于hessian)

 

总上所述:

   kryo为了保证序列化的高效性,会加载需要序列化的类,这会带来一定的消耗。可以理解为kryo本身的消耗。由于这点消耗从而可以保证序列化后的大小(避免不必要的源数据)比较小和快速的反序列化。

  通过变长的int和long值保证这种基本数据类型序列化后尽量小

  通过最后一位的特殊操作而非写入长度来标记字段的范围

  本篇未涉及到的地方还有:

使用开源工具reflectasm进行反射而非java本身的反射

        使用objenesis来创建无默认构造函数的类的对象



为什么kryo比其它的序列化方案要快?

为每一个类分配一个id

实现了自己的IntMap

代码中一些取巧的地方:

利用变量memoizedRegistration和memoizedType记录上一次的调用writeObject函数的Class,则如果两次写入同一类型时,可以直接拿到,不再查找HashMap。

这个也许是为什么在测试中kryo要比其它类库要快的原因之一。








猜你喜欢

转载自blog.csdn.net/varyall/article/details/80215601