【原】Kryo序列化篇
Kryo是一个快速有效的对象图序列化Java库。它的目标是快速、高效、易使用。该项目适用于对象持久化到文件或数据库中或通过网络传输。Kryo还可以自动实现深浅的拷贝/克隆。 就是直接复制一个对象对象到另一个对象,而不是对象转换为字节然后转化为对象。
目前已经被用在下列项目中:
KryoNet (NIO networking)
Twitter's Scalding (Scala API for Cascading)
Twitter's Chill (Kryo serializers for Scala)
Apache Fluo (Kryo is default serialization for Fluo Recipes)
Apache Hive (query plan serialization)
Apache Spark (shuffled/cached data serialization)
DataNucleus (JDO/JPA persistence framework)
CloudPelican
Yahoo's S4 (distributed stream computing)
Storm (distributed realtime computation system, in turn used by many others)
Cascalog (Clojure/Java data processing and querying details)
memcached-session-manager (Tomcat high-availability sessions)
Mobility-RPC (RPC enabling distributed applications)
akka-kryo-serialization (Kryo serializers for Akka)
Groupon
Jive
DestroyAllHumans (controls a robot!)
kryo-serializers (additional serializers)
How
Kryo序列化实例:
Kryo kryo = new Kryo();
// ...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();
Kryo默认为不同的数据类型定义了不同的序列化器,其具体类型如下所示:
| col1 | col2 | col3 | col4 | col5 |
|---|---|---|---|---|
| boolean | Boolean | byte | Byte | char |
| Character | short | Short | int | Integer |
| long | Long | float | Float | double |
| Double | byte[] | String | BigInteger | BigDecimal |
| Collection | Date | Collections.emptyList | Collections.singleton | Map |
| StringBuilder | TreeMap | Collections.emptyMap | Collections.emptySet | KryoSerializable |
| StringBuffer | Class | Collections.singletonList | Collections.singletonMap | Currency |
| Calendar | TimeZone | Enum | EnumSet |
Kryo类在构造参数中会为上述表中的类型初始化对应的序列化类。
其它类会使用默认序列化器FieldSerializer,当然你也可以通过下面的代码更改默认序列化器:
Kryo kryo = new Kryo();
kryo.setDefaultSerializer(AnotherGenericSerializer.class);
也可以为每个类指定序列化类,如下
Kryo kryo = new Kryo();
kryo.register(SomeClass.class, new SomeSerializer());
kryo.register(AnotherClass.class, new AnotherSerializer());
Why
1.下面通过以下Kryo4.0源代码看一下
Kryo类的构造函数为:
public Kryo (ClassResolver classResolver, ReferenceResolver referenceResolver, StreamFactory streamFactory) {
if (classResolver == null) throw new IllegalArgumentException("classResolver cannot be null.");
this.classResolver = classResolver;
classResolver.setKryo(this);
this.streamFactory = streamFactory;
streamFactory.setKryo(this);
this.referenceResolver = referenceResolver;
if (referenceResolver != null) {
referenceResolver.setKryo(this);
references = true;
}
//private final ArrayList<DefaultSerializerEntry> defaultSerializers = new ArrayList(33);用一个大小为33的Entry来存放类及序列化器
addDefaultSerializer(byte[].class, ByteArraySerializer.class);
addDefaultSerializer(char[].class, CharArraySerializer.class);
addDefaultSerializer(short[].class, ShortArraySerializer.class);
addDefaultSerializer(int[].class, IntArraySerializer.class);
addDefaultSerializer(long[].class, LongArraySerializer.class);
addDefaultSerializer(float[].class, FloatArraySerializer.class);
addDefaultSerializer(double[].class, DoubleArraySerializer.class);
addDefaultSerializer(boolean[].class, BooleanArraySerializer.class);
addDefaultSerializer(String[].class, StringArraySerializer.class);
addDefaultSerializer(Object[].class, ObjectArraySerializer.class);
addDefaultSerializer(KryoSerializable.class, KryoSerializableSerializer.class);
addDefaultSerializer(BigInteger.class, BigIntegerSerializer.class);
addDefaultSerializer(BigDecimal.class, BigDecimalSerializer.class);
addDefaultSerializer(Class.class, ClassSerializer.class);
addDefaultSerializer(Date.class, DateSerializer.class);
addDefaultSerializer(Enum.class, EnumSerializer.class);
addDefaultSerializer(EnumSet.class, EnumSetSerializer.class);
addDefaultSerializer(Currency.class, CurrencySerializer.class);
addDefaultSerializer(StringBuffer.class, StringBufferSerializer.class);
addDefaultSerializer(StringBuilder.class, StringBuilderSerializer.class);
addDefaultSerializer(Collections.EMPTY_LIST.getClass(), CollectionsEmptyListSerializer.class);
addDefaultSerializer(Collections.EMPTY_MAP.getClass(), CollectionsEmptyMapSerializer.class);
addDefaultSerializer(Collections.EMPTY_SET.getClass(), CollectionsEmptySetSerializer.class);
addDefaultSerializer(Collections.singletonList(null).getClass(), CollectionsSingletonListSerializer.class);
addDefaultSerializer(Collections.singletonMap(null, null).getClass(), CollectionsSingletonMapSerializer.class);
addDefaultSerializer(Collections.singleton(null).getClass(), CollectionsSingletonSetSerializer.class);
addDefaultSerializer(TreeSet.class, TreeSetSerializer.class);
addDefaultSerializer(Collection.class, CollectionSerializer.class);
addDefaultSerializer(TreeMap.class, TreeMapSerializer.class);
addDefaultSerializer(Map.class, MapSerializer.class);
addDefaultSerializer(TimeZone.class, TimeZoneSerializer.class);
addDefaultSerializer(Calendar.class, CalendarSerializer.class);
addDefaultSerializer(Locale.class, LocaleSerializer.class);
addDefaultSerializer(Charset.class, CharsetSerializer.class);
addDefaultSerializer(URL.class, URLSerializer.class);
OptionalSerializers.addDefaultSerializers(this);
TimeSerializers.addDefaultSerializers(this);
lowPriorityDefaultSerializerCount = defaultSerializers.size();
// Primitives and string. Primitive wrappers automatically use the same registration as primitives.
register(int.class, new IntSerializer());
register(String.class, new StringSerializer());
register(float.class, new FloatSerializer());
register(boolean.class, new BooleanSerializer());
register(byte.class, new ByteSerializer());
register(char.class, new CharSerializer());
register(short.class, new ShortSerializer());
register(long.class, new LongSerializer());
register(double.class, new DoubleSerializer());
register(void.class, new VoidSerializer());
}
- Kryo:可看做类与序列化类的Map集合
- ClassResolver :负责类的注册、根据类标识序列化、根据字节码得到类标识
- ReferenceResolver接口 :当允许引用时,该类用于跟踪已经读写的对象,为写对象提供ID,根据ID读取对象。
它有两个实现子类:ListReferenceResolver和MapReferenceResolver - StreamFactory接口 :基于系统配置提供输入和输出流。
它有两个实现子类:DefaultStreamFactory和FastestStreamFactory
2.为什么在使用一个类之前先要将Kryo注册一下?
在序列化时写一个类名是低效的,所以用一个ID来替代类名,只需要使用前完成注册即可,代码如下:
//用先一个可用的整型ID来注册该类,如果类已经被注册,那么就返回之前的注册信息类
public Registration register (Class type) {
Registration registration = classResolver.getRegistration(type);
if (registration != null) return registration;
return register(type, getDefaultSerializer(type));
}
//和上面的基本一样,只不过是自己定义ID
public Registration register (Class type, int id) {
Registration registration = classResolver.getRegistration(type);
if (registration != null) return registration;
return register(type, getDefaultSerializer(type), id);
}
参考资料
QA
官方文档中有一段话:
Using Unsafe-based IO may result in a quite significant performance boost (sometimes up-to an order of magnitude), depending on your application. In particular, it helps a lot when serializing large primitive arrays as part of your object graphs.
下面是答案:
Unsafe-based IO uses methods from sun.misc.Unsafe for reading and writing from/to memory. Many of those methods map almost 1:1 to processor instructions. Moreover, reading/writing of arrays of native types is executed in bulk instead of doing it element-by-element as it is usually done by Kryo. Together, these features often provide a significant performance boost.
【原】Kryo序列化篇的更多相关文章
- 【Spark调优】Kryo序列化
[Java序列化与反序列化] Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程.序列化使用场景:1.数据的持久化,通过序列化可以把数据永久 ...
- 在Spark中自定义Kryo序列化输入输出API(转)
原文链接:在Spark中自定义Kryo序列化输入输出API 在Spark中内置支持两种系列化格式:(1).Java serialization:(2).Kryo serialization.在默认情况 ...
- Spark 性能相关参数配置详解-压缩与序列化篇
随着Spark的逐渐成熟完善, 越来越多的可配置参数被添加到Spark中来, 本文试图通过阐述这其中部分参数的工作原理和配置思路, 和大家一起探讨一下如何根据实际场合对Spark进行配置优化. 由于篇 ...
- Spark优化之三:Kryo序列化
Spark默认采用Java的序列化器,这里建议采用Kryo序列化提高性能.实测性能最高甚至提高一倍. Spark之所以不默认使用Kryo序列化,可能的原因是需要对类进行注册. Java程序中注册很简单 ...
- 在Spark中使用Kryo序列化
spark序列化 对于优化<网络性能>极为重要,将RDD以序列化格式来保存减少内存占用. spark.serializer=org.apache.spark.serializer.Jav ...
- Spark:将RDD[List[String,List[Person]]]中的List[Person]通过spark api保存为hdfs文件时一直出现not serializable task,没办法找到"spark自定义Kryo序列化输入输出API"
声明:本文转自<在Spark中自定义Kryo序列化输入输出API> 在Spark中内置支持两种系列化格式:(1).Java serialization:(2).Kryo seriali ...
- java原生序列化和Kryo序列化性能比较
简介 最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括: 专门针对Java语言的:Kryo,FST等等 跨语言的:Protostuff,ProtoBuf,Thrift, ...
- Spark设置Kryo序列化缓冲区大小
背景 今天在开发SparkRDD的过程中出现Buffer Overflow错误,查看具体Yarn日志后发现是因为Kryo序列化缓冲区溢出了,日志建议调大spark.kryoserializer.buf ...
- Hadoop2源码分析-序列化篇
1.概述 上一篇我们了解了MapReduce的相关流程,包含MapReduce V2的重构思路,新的设计架构,与MapReduce V1的区别等内容,今天我们在来学习下在Hadoop V2中的序列化的 ...
随机推荐
- 毕向东JAVA视频讲解(第六课)
用java语言对现实生活中的事物进行描述. 通过类的形式来体现的. 怎么描述呢? 对于事物描述通常只关注两方面. 一个是属性,一个是行为. 只要明确该事物的属性和行为并定义在类中即可. 对象:其实就是 ...
- Apache与Tomcat整合
Apache与Tomcat整合 一 Apache与Tomcat比较联系 apache支持静态页,tomcat支持动态的,比如servlet等. 一般使用apache+tomcat的话,apache ...
- mysql23个知识点
1.它是一种解释语言:写一句执行一句,不需要整体编译执行. 2.1.没有“ ”,字符串使用‘ '包含 3.一个表只有一个主键,但是一个主键可以是由多个字段组成的 组合键 4.实体完整性:实体就是指一条 ...
- TCL语言笔记:TCL中的列表操作
一.介绍 列表则是具有特殊解释的字符串.Tcl 中的列表操作和其它 Tcl 命令一样具有相同的结构.列表可应用在诸如 foreach 这样的以列表为变元的循环命令中,也应于构建 eval 命令的延迟命 ...
- PCB板的价格是怎么算出来的?
Part 1 :影响一块PCB板价格的各种因素 PCB的价格是很多采购者一直很困惑的事情,很多人在线下单时也会疑问这些价格是怎么算出来的,下面我们就一起谈论一下PCB价格的组成因素. 1.PCB所用材 ...
- photoshop:多边形选项
你会制作圆滑的五角星吗? 以五边形为例:
- AE数据加载
1. 数据加载问题: 任何系统都离不开数据的加载,下边就AE中几种常用的数据加载做一个列举.以便查阅: 1.加载个人数据库 个人数据库是保存在Access中的数据库.其加载方式有两种:通过名字和通过属 ...
- 1、Singleton 单件(创建模式)
一.Singleton模式主要应用在一些特殊的类,在整个系统运行中,有且仅有一个实例的场景 二.Singleton模式分为单线程与多线程情况,当然多线程一样适应单线程 单线程:在这种情况下比较容易,因 ...
- JavaMail如何保证邮件发送成功
使用过JavaMail的api发送邮件的人可能会有这样一个疑惑:我如何知道我调用该api发送的邮件是否成功呢?一般的开放的api给我们调用都会有个返回值或者状态码,来告诉我们执行成功与否.但是Java ...
- javascript中===与==
== equality 等同,=== identity 恒等. ==, 两边值类型不同的时候,要先进行类型转换,再比较. ===,不做类型转换,类型不同的一定不等. 类型转换规则:Boolean> ...