Kryo 为什么比 Hessian 快
Kryo 是一个快速高效的Java对象图形序列化框架,它原生支持java,且在java的序列化上甚至优于google著名的序列化框架protobuf。由于 protobuf需要编写Schema文件(.proto),且需静态编译。故选择与Kryo类似的序列化框架Hessian作为比较来了解一下Kryo 为什么这么快。
序列化的过程中主要有3个指标:
1、对象序列化后的大小
一个对象会被序列化工具序列化为一串byte数组,这其中包含了对象的field值以及元数据信息,使其可以被反序列化回一个对象
2、序列化与反序列化的速度
一个对象被序列化成byte数组的时间取决于它生成/解析byte数组的方法
3、序列化工具本身的速度
序列化工具本身创建会有一定的消耗。
从序列化后的大小入手:
测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class Simple implements java.io.Serializable{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } static Simple getSimple() { Simple simple = new Simple(); simple.setAge( 10 ); simple.setName( "XiaoMing" ); return simple; } } |
Kryo序列化:
1
2
3
4
5
6
7
|
Kryo kryo = new Kryo(); kryo.setReferences( false ); kryo.setRegistrationRequired( false ); kryo.setInstantiatorStrategy( new StdInstantiatorStrategy()); output.setOutputStream( new FileOutputStream( "file.bin" )); kryo.writeClassAndObject(output, Simple.getSimple()); 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序列化:
1
2
|
HessianOutput hout = new HessianOutput( new FileOutputStream( "hessian.bin" )); hout.writeObject(Simple.getSimple()); <span></span><span></span> |
查看序列化后的结果:
红色部分: 对象头
黑色部分: 对象所属的类名(类名的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,默认支持以下十种。见表一
表一:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# the number of milliseconds since January 1 , 1970 , 00 : 00 : 00 GMT date ::= x01 x00 <the number of milliseconds since January 1 , 1970 , 00 : 00 : 00 GMT> # boolean true / false boolean ::= x02 x01 # true ::= x02 x00 # false # 8 -bit binary data byte ::= x03 <binary-data> # binary-data # char char ::= x04 x00 <binary-data> # binary-data # short short ::= x05 [x00-x7F] [x01-xFF] # 0 to 32767 ::= x05 [x80-xFF] [x01-xFF] # - 23768 to - 1 # 32 -bit signed integer( + x02 when increment) int ::= x06 x01 [x00-x7E] # 0 to 63 ::= x06 x01 [x80-x9E] [x04-xFF] # 64 to 4095 ::= x06 x01 [xA0-xBE] [x00-xFF] [x01-xFF] # 4096 to 1048575 ::= x06 x01 [xC0-xDE] [x00-xFF] [x00-xFF] [x01-xFF] # 1048576 to 268435455 ::= x06 x01 [xE0-xFE] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x07] # 268435456 to 2147483647 ::= x06 x01 [x01-x7F] # - 1 to - 64 ::= x06 x01 [x81-x9F] [x04-xFF] # - 65 to - 4096 ::= x06 x01 [xA1-xBF] [x00-xFF] [x01-xFF] # - 4097 to - 1048576 ::= x06 x01 [xC1-xDF] [x00-xFF] [x00-xFF] [x01-xFF] # - 1048577 to - 268435456 ::= x06 x01 [xE1-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x07] # - 268435457 to - 2147483648 # 64 -bit signed long integer ( +x02 when incerment) long ::= x07 x01 [x00-x7E] # 0 to 63 ::= x07 x01 [x80-x8E] [x08-xFF] # 64 to 2047 ::= x07 x01 [x90-x9E] [x00-xFF] [x01-xFF] # 2048 to 524287 ::= x07 x01 [xA0-xAE] [x00-xFF] [x00-xFF] [x01-xFF] # 524288 to 134217727 ::= x07 x01 [xB0-xBE] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 134217728 to 34359738367 ::= x07 x01 [xC0-xCE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 34359738368 to 8796093022207 ::= x07 x01 [xD0-xDE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 8796093022208 to 2251799813685247 ::= x07 x01 [xE0-xEE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 2251799813685248 to 576460752303423487 ::= x07 x01 [xF0-xFE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x0F] # 576460752303423488 to 9223372036854775807 ::= x07 x01 [x01-x7F] # - 1 to - 64 ::= x07 x01 [x81-x8F] [x08-xFF] # - 65 to - 2048 ::= x07 x01 [x91-x9F] [x00-xFF] [x01-xFF] # - 2049 to - 524288 ::= x07 x01 [xA1-xAF] [x00-xFF] [x00-xFF] [x01-xFF] # - 524289 to - 134217728 ::= x07 x01 [xB1-xBF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # - 134217729 to - 34359738368 ::= x07 x01 [xC1-xCF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # - 34359738369 to - 8796093022208 ::= x07 x01 [xD1-xDF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # - 8796093022209 to - 2251799813685248 ::= x07 x01 [xE1-xEF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # - 2251799813685249 to - 576460752303423488 ::= x07 x01 [xF1-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x0F] # - 576460752303423489 to - 9223372036854775808 # float /Float float ::= x08 x01 <floatToInt> # double /Double double ::= x09 x01 <doubleToLong> # String String ::= x0A x01 x82 <utf8-data> # data.length()= 1 ::= x0A x01 <utf8-data.subString( 0 ,data.length()- 2 )> <utf8-data.charAt(data.length- 1 )>+x70 # data.length()> 1 # The class not registered in kryo Object ::= x01 x00 <(string)className> <( byte )id> <(Object)objectFieldValue ordered by fieldName> |
via http://x-rip.iteye.com/blog/1555344
Kryo 为什么比 Hessian 快的更多相关文章
- Java 序列化界新贵 kryo 和熟悉的“老大哥”,就是 PowerJob 的序列化方案
本文适合有 Java 基础知识的人群 作者:HelloGitHub-Salieri HelloGitHub 推出的<讲解开源项目>系列. 项目地址: https://github.com/ ...
- Netty实现高性能RPC服务器优化篇之消息序列化
在本人写的前一篇文章中,谈及有关如何利用Netty开发实现,高性能RPC服务器的一些设计思路.设计原理,以及具体的实现方案(具体参见:谈谈如何使用Netty开发实现高性能的RPC服务器).在文章的最后 ...
- 基于apache的tomcat负载均衡和集群配置session共享
接上面的话题接着继续完善.为什么没接到上篇呢?原因很简单太长的文章不爱看!就像有人写了上千行的方法一样,不是逼得没办法谁爱看谁看,反正我不看. 期间我没有一次配置成功,从失败的开始说起, 1.准备ja ...
- Netty实现高性能RPC服务器
在本人写的前一篇文章中,谈及有关如何利用Netty开发实现,高性能RPC服务器的一些设计思路.设计原理,以及具体的实现方案(具体参见:谈谈如何使用Netty开发实现高性能的RPC服务器).在文章的最后 ...
- 【Spark学习】Apache Spark调优
Spark版本:1.1.0 本文系以开源中国社区的译文为基础,结合官方文档翻译修订而来,转载请注明以下链接: http://www.cnblogs.com/zhangningbo/p/4117981. ...
- Spark的性能调优杂谈
下面这些关于Spark的性能调优项,有的是来自官方的,有的是来自别的的工程师,有的则是我自己总结的. 基本概念和原则 <1> 每一台host上面可以并行N个worker,每一个worke ...
- Spark 调优(转)
Spark 调优 返回原文英文原文:Tuning Spark Because of the in-memory nature of most Spark computations, Spark pro ...
- 基于Memcached的tomcat集群session共享所用的jar
多个tomcat各种序列化策略配置如下:一.java默认序列化tomcat配置conf/context.xml添加<Manager className="de.javakaffee.w ...
- 【译】Spark调优
原文地址:http://spark.incubator.apache.org/docs/0.7.3/tuning.html 译文地址:http://www.oschina.net/translate/ ...
随机推荐
- iOS 通览(二)
一.关键词 extern:C语言的函数外部声明. 如果你要在一个.c或者.m中使用另外一个.c文件的函数的话,需要在文件中写入目标函数的外部引用的声明. 二.自定义View 自定义View添加控件对象 ...
- Visual Studio 中TODO List的使用
http://msdn.microsoft.com/en-us/library/txtwdysk.aspx 工欲善其事,必先利其器 When the Task List is open, you ca ...
- 3.5 spring-replaced-method 子元素的使用与解析
1.replaced-method 子元素 方法替换: 可以在运行时用新的方法替换现有的方法,与之前的 look-up不同的是replace-method 不但可以动态地替换返回的实体bean,而且可 ...
- [转载]test后跟je
今天俺也用OD(OllyDbg)反汇编了个小软件,其中里面有下面两条指令: 没太明白什么意思,google一下,在看雪论坛上发现了一个大虾的解释很详细,记录一下: 1.test a,b 是a与b相与的 ...
- 团体程序设计天梯赛-练习集L1-013. 计算阶乘和
L1-013. 计算阶乘和 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 对于给定的正整数N,需要你计算 S = 1! + 2 ...
- 利用钩子函数来捕捉键盘响应的windows应用程序
一:引言: 你也许一直对金山词霸的屏幕抓词的实现原理感到困惑,你也许希望将你的键盘,鼠标的活动适时的记录下来,甚至你想知道木马在windows操作系统是怎样进行木马dll的加载的…..其实这些都是用到 ...
- hdu 4726
贪心 不是很难 各种细节注意 #include <cstdio> #include <cstring> #include <algorithm> using na ...
- Debugging with GDB 用GDB调试多线程程序
Debugging with GDB http://www.delorie.com/gnu/docs/gdb/gdb_25.html GDB调试多线程程序总结 一直对GDB多线程调试接触不多,最近因为 ...
- linq集合内部赋值
linq集合内部赋值 比如将一个列的值,赋值给另一列 有三种方法: 1. e.Result.ToList().ForEach(n => n.IsIntermediarybool = SetIsI ...
- What is the innovator’s solution——什么才是创新的解决方案1
最近学习MOT(management of Technology),研读了Christensen的<创新者的窘境>和<创新者的解答>,以下简称创新者系列.总觉得需要写点儿什么. ...