Kryo为什么比Hessian快

转载 2018年04月16日 01:02:56

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

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

1、对象序列化后的大小

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

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

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

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

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

 

从序列化后的大小入手:

测试类:

 

Java代码  收藏代码
  1. public class Simple implements java.io.Serializable{  
  2.   private String name;  
  3.   private int age;  
  4.   
  5.   
  6.   public String getName() {  
  7.     return name;  
  8.   }  
  9.   
  10.   public void setName(String name) {  
  11.     this.name = name;  
  12.   }  
  13.   
  14.   public int getAge() {  
  15.     return age;  
  16.   }  
  17.   
  18.   public void setAge(int age) {  
  19.     this.age = age;  
  20.   }  
  21.   
  22.   static Simple getSimple() {  
  23.     Simple simple = new Simple();  
  24.     simple.setAge(10);  
  25.     simple.setName("XiaoMing");  
  26.     return simple;  
  27.   }  
  28. }  

 Kryo序列化:

 

Java代码  收藏代码
  1. Kryo kryo = new Kryo();  
  2. kryo.setReferences(false);  
  3. kryo.setRegistrationRequired(false);  
  4. kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());  
  5. output.setOutputStream(new FileOutputStream("file.bin"));  
  6. kryo.writeClassAndObject(output, Simple.getSimple());  
  7. output.flush();  

 查看序列化后的结果:



 红色部分:对象头,01 00代表一个未注册过的类

 黑色部分:对象所属的class的名字(kryo中没有设定某个字段的结束符,对于String这种不定长的byte数组,kryo会在其最后一个byte字节加上x70,如类名最后一位为e,其askii码为x65,在其基础上加x70,即为E5)

 绿色部分:表示这个对象在对象图中的id。即simple对象在对象图中的id为01.

 蓝色部分:表示该类的field。其中02 14中14表示int数值10(映射关系见表1),02和绿色部分的01意思是一样的,即10这个int对象在对象图中的id为02。以此类推,03表示对象图中的第三个对象,即XiaoMing这个String,同样其最后一位byte被加了x70。

Hessian序列化:

 

Java代码  收藏代码
  1. HessianOutput hout = new HessianOutput(new FileOutputStream("hessian.bin"));  
  2. hout.writeObject(Simple.getSimple());  

 查看序列化后的结果:





 
 
 红色部分: 对象头

 黑色部分: 对象所属的类名(类名的askii码)

 紫色部分: 字节类型描述符,表示之后的字节属于何种类型,53表示String,49表示int,等等

 绿色部分: 字节长度描述符,用于表示后面的多少个字节是表示该字节组的

 白色部分: field实际的类型的byte值

 蓝色部分: filed实际的value

 7A: 结束符

 

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

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目前只支持Java,所以官方文档也没有给出它序列化所用的kryo grammer,默认支持以下十种。见表一

表一:

 

Grammer代码  收藏代码
  1.            # the number of milliseconds since January 1197000:00:00 GMT  
  2. date       ::= x01 x00 <the number of milliseconds since January 1197000:00:00 GMT>  
  3.   
  4.            # boolean true/false  
  5. boolean ::= x02 x01 # true  
  6.               ::= x02 x00   # false  
  7.              
  8.            # 8-bit binary data  
  9. byte       ::= x03 <binary-data>  # binary-data    
  10.   
  11.            # char  
  12. char       ::= x04 x00 <binary-data>  # binary-data    
  13.       
  14.            # short  
  15. short   ::= x05 [x00-x7F] [x01-xFF] # 0 to 32767   
  16.        ::= x05 [x80-xFF] [x01-xFF]  # -23768 to -1  
  17.              
  18.            # 32-bit signed integer( + x02 when increment)  
  19. int       ::= x06 x01 [x00-x7E]                                 # 0 to 63  
  20.            ::= x06 x01 [x80-x9E] [x04-xFF]                                  # 64 to 4095  
  21.            ::= x06 x01 [xA0-xBE] [x00-xFF] [x01-xFF]                    # 4096 to 1048575  
  22.            ::= x06 x01 [xC0-xDE] [x00-xFF] [x00-xFF] [x01-xFF]              # 1048576 to 268435455  
  23.        ::= x06 x01 [xE0-xFE] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x07]    # 268435456 to 2147483647  
  24.            ::= x06 x01 [x01-x7F]                                    # -1 to -64  
  25.            ::= x06 x01 [x81-x9F] [x04-xFF]                                  # -65 to -4096  
  26.            ::= x06 x01 [xA1-xBF] [x00-xFF] [x01-xFF]                    # -4097 to -1048576  
  27.            ::= x06 x01 [xC1-xDF] [x00-xFF] [x00-xFF] [x01-xFF]              # -1048577 to -268435456  
  28.            ::= x06 x01 [xE1-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x07]    # -268435457 to -2147483648  
  29.              
  30.            # 64-bit signed long integer ( +x02 when incerment)  
  31. long       ::= x07 x01 [x00-x7E]                                                                                        # 0 to 63  
  32.            ::= x07 x01 [x80-x8E] [x08-xFF]                                                                              # 64 to 2047  
  33.            ::= x07 x01 [x90-x9E] [x00-xFF] [x01-xFF]                                                                    # 2048 to 524287  
  34.            ::= x07 x01 [xA0-xAE] [x00-xFF] [x00-xFF] [x01-xFF]                                                          # 524288 to 134217727  
  35.            ::= x07 x01 [xB0-xBE] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                                                # 134217728 to 34359738367  
  36.        ::= x07 x01 [xC0-xCE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                                      # 34359738368 to 8796093022207  
  37.            ::= x07 x01 [xD0-xDE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                            # 8796093022208 to 2251799813685247  
  38.        ::= x07 x01 [xE0-xEE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                  # 2251799813685248 to 576460752303423487  
  39.        ::= x07 x01 [xF0-xFE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x0F]        # 576460752303423488 to 9223372036854775807  
  40.        ::= x07 x01 [x01-x7F]                                                                                        # -1 to -64  
  41.            ::= x07 x01 [x81-x8F] [x08-xFF]                                                                              # -65 to -2048  
  42.            ::= x07 x01 [x91-x9F] [x00-xFF] [x01-xFF]                                                                    # -2049 to -524288  
  43.            ::= x07 x01 [xA1-xAF] [x00-xFF] [x00-xFF] [x01-xFF]                                                          # -524289 to -134217728  
  44.            ::= x07 x01 [xB1-xBF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                                                # -134217729 to -34359738368  
  45.        ::= x07 x01 [xC1-xCF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                                      # -34359738369 to -8796093022208  
  46.        ::= x07 x01 [xD1-xDF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                            # -8796093022209 to -2251799813685248  
  47.        ::= x07 x01 [xE1-xEF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF]                  # -2251799813685249 to -576460752303423488  
  48.        ::= x07 x01 [xF1-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x0F]        # -576460752303423489 to -9223372036854775808  
  49.     
  50.            # float/Float  
  51. float      ::= x08 x01 <floatToInt>  
  52.   
  53.            # double/Double  
  54. double     ::= x09 x01 <doubleToLong>  
  55.   
  56.            # String  
  57. String     ::= x0A x01 x82 <utf8-data>                                                                    # data.length()=1  
  58.            ::= x0A x01 <utf8-data.subString(0,data.length()-2)> <utf8-data.charAt(data.length-1)>+x70   # data.length()>1  
  59.   
  60.             # The class not registered in kryo  
  61. Object  ::= x01 x00 <(string)className> <(byte)id> <(Object)objectFieldValue ordered by fieldName>   



https://blog.csdn.net/sdujava2011/article/details/78199562





Kryo 为什么比 Hessian 快

Kryo 是一个快速高效的Java对象图形序列化框架,它原生支持java,且在java的序列化上甚至优于google著名的序列化框架protobuf。由于 protobuf需要编写Schema文件(....
  • jmppok
  • jmppok
  • 2015-03-18 14:16:37
  • 902

Spark---性能调优之使用Kryo序列化

1、Spark默认的序列化机制和Kryo序列化机制相比有什么优势? 默认情况下,Spark内部是使用Java的序列化机制,ObjectOutputStream / ObjectInputStream,...
  • tian_qing_lei
  • tian_qing_lei
  • 2017-09-14 23:06:17
  • 264

序列化框架的使用及性能对比Kryo、Hessian、Protostuff、java原生

序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创...
  • qq_21033663
  • qq_21033663
  • 2016-07-25 19:25:44
  • 2107

Kryo、msgpack、protobuf、Hessian、Avro、Thrift等序列化框架比较

最近一直在想如果让我自己来做一个服务化框架出来,该实现些什么功能,具体该怎么去做这样的问题,数据序列化是一个重要的模块,故此有意对常见的一些开源序列化框架做一个比较! 我个人对Hessian、Jav...
  • zhangzhaokun
  • zhangzhaokun
  • 2013-08-01 17:55:34
  • 10879

【Java.ThirdParty】序列化框架性能对比(kryo、hessian、java、protostuff)

转自:http://blog.csdn.net/jmppok/article/details/44409693 序列化框架性能对比(kryo、hessian、java、protostuf...
  • robinjwong
  • robinjwong
  • 2015-04-03 16:51:25
  • 13749

Java kryo/protobuf/protostuff序列化 or Json 性能对比

文章搬家至https://lcy362.github.io/posts/57802/ 对于一个java object的序列化,想测一下使用json和使用一般序列化工具,在时间性能、空间性能上的区别。...
  • lcy362
  • lcy362
  • 2017-03-02 18:10:20
  • 2708

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

序列化框架性能对比(kryo、hessian、java、protostuff) 简介:   优点 缺点 Kryo 速度...
  • jmppok
  • jmppok
  • 2015-03-18 14:13:40
  • 8860

java序列化框架(protobuf、thrift、kryo、fst、fastjson、Jackson、gson、hessian)性能对比

我们为什么要序列化     举个栗子:下雨天我们要打伞,但是之后我们要把伞折叠起来,方便我们存放。那么运用到我们java中道理是一样的,我们要将数据分解成字节流,以便存储在文件中或在网络上传输,这...
  • fenglongmiao
  • fenglongmiao
  • 2018-03-02 17:00:15
  • 104

hessian 序列化实现 初探

众所周知大名鼎鼎的开源remoting的框架hessian的速度是非常快的,有人做过测试:一个UserData类,有一个字符串属性,一个日期属性,一个double属性,分别用java,hessian来...
  • lyasua
  • lyasua
  • 2014-05-16 11:32:06
  • 1422

Kryo 进阶学习:数据的压缩与加密

压缩用Kryo提供的DeflateSerializer类,然后外加
  • rocklee
  • rocklee
  • 2014-05-23 14:59:16
  • 1733
收藏助手
不良信息举报
您举报文章:Kryo为什么比Hessian快
举报原因:
原因补充:

(最多只允许输入30个字)