`
x-rip
  • 浏览: 106926 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Kryo为什么比Hessian快

 
阅读更多

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

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

1、对象序列化后的大小

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

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

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

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

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

 

从序列化后的大小入手:

测试类:

 

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序列化:

 

    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序列化:

 

    HessianOutput hout = new HessianOutput(new FileOutputStream("hessian.bin"));
    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,默认支持以下十种。见表一

表一:

 

           # 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> 

 

 

  • 大小: 16.6 KB
  • 大小: 22.8 KB
分享到:
评论
3 楼 xurping 2018-05-23  
kolor 写道
呵呵 ,一直在用kryo,不过都没有去分析过它生成的字节码,学习了
不过,kryo有个缺陷,它生成的字节码中是不包含field元数据的,这样的话,在兼容性上就很难处理了,比如你文中提到的类Simple,它有两个字段,假如后来又给它增加了个字段,这样新旧实体就没法兼容了


可以通过自定义序列化器实现兼容
2 楼 xjl456852 2016-07-19  
你好,我感觉那个加x70是不是有问题啊.

x65在其基础上加x70 得到的结果不是xD5吗? 怎么会是xE5呢
1 楼 kolor 2012-09-07  
呵呵 ,一直在用kryo,不过都没有去分析过它生成的字节码,学习了
不过,kryo有个缺陷,它生成的字节码中是不包含field元数据的,这样的话,在兼容性上就很难处理了,比如你文中提到的类Simple,它有两个字段,假如后来又给它增加了个字段,这样新旧实体就没法兼容了

相关推荐

    java版分销系统源码-NettyRPC:NettyRPC是基于Netty的高性能javarpc服务器,使用kryo,hessian,prot

    消息网络传输除了JDK原生的对象序列化方式,还支持目前主流的编码解码器:kryo、hessian。 Netty网络模型采用主从Reactor线程模型,提升RPC服务器并行吞吐性能。 多线程模型采用guava线程库进行封装。 NettyRPC 1.0 ...

    基于Netty的高性能RPC框架 .zip

    NettyRPC是一个基于Netty构建的高性能Java RPC服务器,支持多种消息序列化方式,如Kryo、Hessian和Protostuff。该项目通过Spring容器管理服务定义和实现,采用主从Reactor线程模型提升服务器并行吞吐性能。 主要...

    快速序列化框架

    本文将对五种常见的快速序列化框架——Google Protobuf、Apache Thrift、Hessian、Avro 和 Kryo 进行详细介绍,并对其性能进行比较。 #### 二、各框架详解 ##### 1. Google Protobuf - **简介**:由Google开发并...

    34_dubbo都支持哪些通信协议以及序列化协议?.zip

    2. **Hessian2**:一种快速的二进制序列化协议,它将Java对象转换为高效的字节流,适合于内部系统间通信。 3. **Fastjson**:阿里巴巴开源的JSON库,它也可以用于序列化和反序列化Java对象,性能较好,且支持复杂的...

    mango:高性能,开源Java RPC框架

    支持各种序列化协议,例如 ,Kryo,Hessian,msgpack,Jackson,Fastjson。 支持高级功能,例如负载平衡(随机,循环),高可用性策略(故障转移,故障转移)。 支持诸如ZooKeeper或Consul之类的服务发现服务。 ...

    My-RPC-Framework:一个简单的RPC框架的实现

    实现了四种序列化算法,Json 方式、Kryo 算法、Hessian 算法与 Google Protobuf 方式(默认采用 Kryo方式序列化) 实现了两种负载均衡算法:随机算法与轮转算法 使用 Nacos 作为注册中心,管理服务提供者信息 消费端...

    RxCache:适用于Java和Android的本地React式缓存。 现在,它支持堆内存,堆外内存和磁盘缓存

    Persistence 额外支持使用 FastJSON、Moshi、Kryo、Hessian、FST、Protobuf 实现对象的序列化和反序列化 Persistence 的 AbstractConverter 拥有加密功能,默认使用 AES 128、DES 算法进行加密 支持显示

    20170723-课堂笔记1

    在Java之外,还有许多其他序列化技术,如JSON、Hessian、XML、protobuf、kryo、MsgPack、FST、thrift和protostuff等,每种技术都有其独特的优点和适用场景。例如,protobuf提供了高效、紧凑的二进制编码,kryo提供了...

    藏经阁-双11万亿流量下的分布式缓存--Tiar技术揭秘.pdf

    同时,Tair技术也对序列化进行了优化,使用kryo和hessian,可以提高吞吐量16%以上。 Tair技术的内存网格机制可以提供高性能计算快速IO能力,满足业务场景的需求。Tair技术的特点包括数据本地性、读穿透、Write ...

    agileway:提供Java,Web,各种类库增强,应避免996。目前已支持feign,redis,datasource,shiro,httpclient,rest,codec,serialize等

    支持基于hessian序列化框架实现 支持基于Jdk Serializable规范实现 支持基于easyjson,jackson实现 支持基于Kryo序列化框架实现 支持基于MsgPack序列化规范的实现 支持基于Protostuff序列化框架实现 支持基于XSON...

    2023年1月最新dubbo面试题

    在序列化方面,Dubbo 提供了多种序列化协议,包括 hessian2、json、nativejava、fst、kryo、avro 和 protobuf。这些协议用于将对象转换成字节流以便在网络间传输,不同的协议在性能、兼容性和数据大小上有各自的特点...

    dubbo官方指南

    5. **协议与序列化(Protocol & Serialization)**:Dubbo支持多种通信协议,如RMI、HTTP、Hessian等,并提供了高效的序列化机制,如FastJson、Kryo等,以优化网络传输效率。 6. **负载均衡(Load Balance)**:...

    lostrpc:异步 rpc frm

    支持很多编码解码器(Protobuf【跨语言】、Hessian、JDK、Kryo) 支持自定义Codec 支持自定义Protocol 实现了消息的同步分发、异步分发 支持自定义消息分发 服务端支持消息同步处理、全局异步处理、链接消息有序异步...

    亲缘关系

    rsocket等协议kinrpc协议支持KRYO,HESSIAN,JAVA,JSON等序列化方案kinrpc协议下支持provider服务接口方法初始化返回结果通过org.kin.kinrpc.rpc.RpcServiceContext设置未来参数返回值是未来进一步工作代码优化, ...

    史上最全40道Dubbo面试题!.zip

    包括Java默认序列化、Hessian2、FastJson、Kryo、protobuf等多种方式,其中Hessian2和FastJson较为常用。 10. **什么是服务暴露(Export)和引用(Refer)?** 服务提供者通过暴露服务,使其可以被远程调用;服务...

    基于java的高性能RPC框架 nfs-rpc.zip

    2. 高效序列化库:如protobuf、Hessian、Kryo等,以减少网络传输的数据量,提升性能。 3. 路由与负载均衡:通过负载均衡算法,如轮询、权重轮询、一致性哈希等,将请求分发到合适的服务器。 4. 服务注册与发现:...

    dubbo升级版jar

    2. **序列化优化**:dubbox支持多种序列化方式,如Hessian2、FastJson、Kryo等,并对这些方式进行性能调优,降低了数据交换的开销。 3. **线程模型优化**:对线程池模型进行了优化,减少了线程上下文切换,提升了...

    Dubbo入门之HelloWorld

    - 序列化(Serialization):负责将Java对象转换为可传输的字节流,如Hessian2、Fastjson、Kryo等。 此外,Dubbo还提供了丰富的扩展点,如Filter、Router、Monitor等,允许开发者根据实际需求定制功能。同时,Dubbo...

    jvm-serializers:比较JVM上的序列化库的基准

    - **FST (Fast Serialization)**:另一个高效库,它的目标是超越Kryo,提供更快的速度和更小的序列化输出。 - **Bson4Jackson**:基于Jackson的BSON实现,BSON是一种轻量级的数据交换格式,类似于JSON,但支持更多...

Global site tag (gtag.js) - Google Analytics