kryo java_优化Java序列化– Java,XML,JSON,Kryo,POF

kryo java

也许我很天真,但是我一直认为Java序列化肯定是将Java对象序列化为二进制形式的最快,最有效的方法。 毕竟Java是第7个主要发行版,所以这不是新技术,而且由于每个JDK似乎都比上一个快,因此我错误地认为序列化现在必须非常快速和高效。 我认为,由于Java序列化是二进制的,并且依赖于语言,因此它必须比XML或JSON更快,更高效。 不幸的是,我错了,如果您担心性能,建议不要使用Java序列化。

现在,请不要误会我的意思,我不是在尝试破坏Java。 Java序列化有许多要求,主要需求是能够将任何东西(或至少任何实现Serializable东西) Serializable到任何其他JVM(甚至是不同的JVM版本/实现)中,甚至运行要序列化的类的不同版本(例如只要您设置了serialVersionUID )。 最主要的是它可以正常工作,而且确实很棒。 性能不是主要要求,并且格式是标准的并且必须向后兼容,因此优化非常困难。 同样,对于许多类型的用例,Java序列化执行得很好。

在研究三层并发基准时,我开始了进入序列化过程的旅程。 我注意到Java序列化过程中花费了大量CPU时间,因此我决定进行调查。 我从序列化具有几个字段的简单Order对象开始。 我序列化了对象并输出了字节。 尽管Order对象只有几个字节的数据,但我并不是天真地认为它将序列化为几个字节,但我对序列化足够了解,因此至少需要写出完整的类名,因此它知道它已序列化的内容,因此可以将其读回。 因此,我期望大约50个字节。 结果超过了600个字节,那时候我意识到Java序列化并不像我想象的那么简单。

Order对象的Java序列化字节

----sr--model.Order----h#-----J--idL--customert--Lmodel/Customer;L--descriptiont--Ljava/lang/String;L--orderLinest--Ljava/util/List;L--totalCostt--Ljava/math/BigDecimal;xp--------ppsr--java.util.ArrayListx-----a----I--sizexp----w-----sr--model.OrderLine--&-1-S----I--lineNumberL--costq-~--L--descriptionq-~--L--ordert--Lmodel/Order;xp----sr--java.math.BigDecimalT--W--(O---I--scaleL--intValt--Ljava/math/BigInteger;xr--java.lang.Number-----------xp----sr--java.math.BigInteger-----;-----I--bitCountI--bitLengthI--firstNonzeroByteNumI--lowestSetBitI--signum[--magnitudet--[Bxq-~----------------------ur--[B------T----xp----xxpq-~--xq-~--

(注意“-”表示不可打印的字符)

您可能已经注意到,Java序列化不仅写出要序列化的对象的完整类名,而且还写出要序列化的类的整个类定义以及所有引用的类。 类定义可能非常大,并且似乎是主要的性能和效率问题,尤其是在编写单个对象时。 如果要写出大量相同类的对象,则类定义开销通常不是大问题。 我注意到的另一件事是,如果您的对象具有对类的引用(例如元数据对象),则Java序列化将编写整个类定义,而不仅仅是类名,因此使用Java序列化来编写元数据非常昂贵。

可外部化

通过实现Externalizable接口可以优化Java序列化。 实现此接口可以避免写出整个类定义,而只需编写类名即可。 它要求您实现readExternalwriteExternal方法,因此需要您进行一些工作和维护,但是比仅实现Serializable可更快,更有效。

关于Externalizable结果的一个有趣注释是,对于少量对象,它的效率要高得多,但对于大量对象,实际上输出的字节数要比Serializable多得多。 我假设Externalizable格式对重复对象的效率稍低。

可外部化的类

public class Order implements Externalizable {private long id;private String description;private BigDecimal totalCost = BigDecimal.valueOf(0);private List orderLines = new ArrayList();private Customer customer;public Order() {}public void readExternal(ObjectInput stream) throws IOException, ClassNotFoundException {this.id = stream.readLong();this.description = (String)stream.readObject();this.totalCost = (BigDecimal)stream.readObject();this.customer = (Customer)stream.readObject();this.orderLines = (List)stream.readObject();}public void writeExternal(ObjectOutput stream) throws IOException {stream.writeLong(this.id);stream.writeObject(this.description);stream.writeObject(this.totalCost);stream.writeObject(this.customer);stream.writeObject(this.orderLines);}
}

Order对象的可外部化的序列化字节

----sr--model.Order---*3--^---xpw---------psr--java.math.BigDecimalT--W--(O---I--scaleL--intValt--Ljava/math/BigInteger;xr--java.lang.Number-----------xp----sr--java.math.BigInteger-----;-----I--bitCountI--bitLengthI--firstNonzeroByteNumI--lowestSetBitI--signum[--magnitudet--[Bxq-~----------------------ur--[B------T----xp----xxpsr--java.util.ArrayListx-----a----I--sizexp----w-----sr--model.OrderLine-!!|---S---xpw-----pq-~--q-~--xxx

其他序列化选项

我开始研究Java中还有哪些其他序列化选项。 我从EclipseLink MOXy开始,它支持通过JAXB API将对象序列化为XML或JSON。 我并不期望XML序列化能胜过Java序列化,因此在某些用例中确实感到惊讶。 我还找到了产品Kryo,这是一个用于优化序列化的开源项目。 我还研究了Oracle Coherence POF序列化格式。 每个产品都有优点和缺点,但我的主要重点是比较它们的性能和效率。

EclipseLink MOXy – XML和JSON

使用EclipseLink MOXy序列化为XML或JSON的主要优点是两者都是标准的可移植格式。 您可以使用任何语言从任何客户端访问数据,因此与Java序列化一样,不限于Java。 您还可以将数据与Web服务和REST服务集成。 两种格式都基于文本,因此易于阅读。 不需要编码或特殊接口,只需元数据。 性能是完全可以接受的,并且对于小型数据集,其性能优于Java序列化。

缺点是文本格式的效率不如优化的二进制格式,并且JAXB需要元数据。 因此,您需要使用JAXB批注对类进行批注,或者提供XML配置文件。 另外,默认情况下不处理循环引用,您需要使用@XmlIDREF来处理循环。

JAXB注释的类

@XmlRootElement
public class Order {@XmlID@XmlAttributeprivate long id;@XmlAttributeprivate String description;@XmlAttributeprivate BigDecimal totalCost = BigDecimal.valueOf(0);private List orderLines = new ArrayList();private Customer customer;
}public class OrderLine {@XmlIDREFprivate Order order;@XmlAttributeprivate int lineNumber;@XmlAttributeprivate String description;@XmlAttributeprivate BigDecimal cost = BigDecimal.valueOf(0);
}

订单对象的EclipseLink MOXy序列化XML

<order id="0" totalCost="0"><orderLines lineNumber="1" cost="0"><order>0</order></orderLines></order>

订单对象的EclipseLink MOXy序列化JSON

{"order":{"id":0,"totalCost":0,"orderLines":[{"lineNumber":1,"cost":0,"order":0}]}}

ry

Kryo是一个快速,高效的Java序列化框架。 Kryo是根据New BSD许可提供的有关Google代码的开源项目。 这是一个只有3个成员的小型项目,它于2009年首次发布,最后一次于2013年2月发布2.21版本,因此仍在积极开发中。

Kryo的工作方式类似于Java序列化,并且尊重瞬态字段,但不需要类可序列化。 我发现Kryo有一些限制,例如要求类具有默认构造函数,并且在序列化java.sql.Time,java.sql.Date和java.sql.Timestamp类时遇到了一些问题。

Order对象的Kryo序列化字节

------java-util-ArrayLis-----model-OrderLin----java-math-BigDecima---------model-Orde-----

Oracle Coherence POF

Oracle Coherence产品提供了自己的优化二进制格式,称为POF(便携式对象格式)。 Oracle Coherence是一种内存数据网格解决方案(分布式缓存)。 一致性是一种商业产品,需要许可证。 EclipseLink通过使用Coherence作为EclipseLink共享缓存的Oracle TopLink Grid产品支持与Oracle Coherence的集成。

POF提供了序列化框架,可以独立于Coherence使用(如果您已经获得Coherence许可)。 POF要求您的类实现PortableObject接口和读/写方法。 您还可以实现单独的Serializer类,或在最新的Coherence版本中使用注释。 POF要求每个类提前分配一个常量ID,因此您需要某种方式确定此ID。 POF格式是一种二进制格式,非常紧凑,高效且快速,但是您需要做一些工作。

对于单个Order / OrderLine对象,POF的总字节为32个字节,对于100个OrderLines,则为1593个字节。 我不会给出结果,因为POF是一种商业许可产品的一部分,但是速度非常快。

POF便携式对象

public class Order implements PortableObject {private long id;private String description;private BigDecimal totalCost = BigDecimal.valueOf(0);private List orderLines = new ArrayList();private Customer customer;public Order() {}public void readExternal(PofReader in) throws IOException {this.id = in.readLong(0);this.description = in.readString(1);this.totalCost = in.readBigDecimal(2);this.customer = (Customer)in.readObject(3);this.orderLines = (List)in.readCollection(4, new ArrayList());}public void writeExternal(PofWriter out) throws IOException {out.writeLong(0, this.id);out.writeString(1, this.description);out.writeBigDecimal(2, this.totalCost);out.writeObject(3, this.customer);out.writeCollection(4, this.orderLines);}
}

Order对象的POF序列化字节

-----B--G---d-U------A--G-------

结果

那么每种表现如何呢? 我做了一个简单的基准比较不同的序列化机制。 我比较了两个不同用例的序列化。 第一个是具有单个OrderLine对象的单个Order对象。 第二个是具有100个OrderLine对象的单个Order对象。 我比较了每秒的平均序列化操作,并测量了序列化数据的字节大小。 不同的对象模型,用例和环境将产生不同的结果,但这使您对不同的序列化器的性能差异有一个大致的了解。

结果表明,对于少量对象,Java序列化速度较慢,但​​对于大量对象,Java序列化速度较好。 相反,对于少量对象,XML和JSON的性能优于Java序列化,但是对于大量对象,Java序列化的速度更快。 Kryo和其他优化的二进制序列化程序在这两种类型的数据上均优于Java序列化。

您可能想知道,为什么不到一毫秒的时间与性能有任何关系是有意义的,而您可能是对的。 通常,如果您写出大量对象,然后Java序列化执行得很好,那么您只会遇到一个实际的性能问题,那么,对于少量对象而言,它的执行效果很差吗? 对于单个操作,这可能是正确的,但是如果执行许多小的序列化操作,则成本相关的。 为许多客户端提供服务的典型服务器通常会发出许多小请求,因此,尽管序列化的成本不足以使这些单个请求中的任何一个花费很长时间,但它将极大地影响服务器的可伸缩性。

用1条订单行订购

序列化器 大小(字节) 序列化(操作/秒) 反序列化(操作/秒) 差异百分比(来自Java序列化) 差异百分比(反序列化)
Java可序列化 636 128,634 19,180 0% 0%
Java可外部化 435 160,549 26,678 24% 39%
EclipseLink MOXy XML 101 348,056 47,334 170% 146%
ry 90 359,368 346,984 179% 1709%

订购100条订单行

序列化器 大小(字节) 序列化(操作/秒) 反序列化(操作/秒) 差异百分比(来自Java序列化) 差异百分比(反序列化)
Java可序列化 2,715 16,470 10,215 0% 0%
Java可外部化 2,811 16,206 11,483 -1% 12%
EclipseLink MOXy XML 6,628 7,304 2,731 -55% -73%
ry 1216 22862 31,499 38% 208%

EclipseLink JPA

在EclipseLink 2.6开发版本(在某种程度上为2.5)中,我们增加了在EclipseLink进行序列化的任何地方选择序列化程序的功能。

这样的地方之一就是序列化@Lob映射。 现在,您可以使用@Convert批注指定序列化程序,例如@Convert(XML),@ Convert(JSON),@ Convert(Kryo)。 除了优化性能之外,这还提供了一种简单的机制将XML和JSON数据写入数据库。

同样对于EclipseLink缓存协调,您可以使用“ eclipselink.cache.coordination.serializer”属性选择序列化器。

这篇文章中使用的基准测试的源代码可以在这里找到,或者在这里下载。

参考: 优化Java序列化– Java Persistence Performance博客上的JCG合作伙伴 James Sutherland的Java,XML,JSON,Kryo和POF 。

翻译自: https://www.javacodegeeks.com/2013/09/optimizing-java-serialization-java-vs-xml-vs-json-vs-kryo-vs-pof.html

kryo java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java数字分类给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:A1 = 能被5整除的数字中所有偶数的和;A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3

题目描述&#xff1a; 给定一系列正整数&#xff0c;请按要求对数字进行分类&#xff0c;并输出以下5个数字&#xff1a; A1 能被5整除的数字中所有偶数的和&#xff1b; A2 将被5除后余1的数字按给出顺序进行交错求和&#xff0c;即计算n1-n2n3-n4…&#xff1b; A3 被5除后…

Windows编程之互动与动画

第五节&#xff1a; 考虑屏幕左侧一台坦克&#xff0c;向水平方向发射一枚炮弹,穿越屏幕。 很自然地&#xff0c;这场景中有坦克和炮弹两个对象&#xff0c;各自有各自坐标&#xff0c;坦克坐标是固定的&#xff0c;而炮弹坐标是变化的。因此有两个结构体类型&#xff1a;Tank…

创新设计模式:工厂模式

以前&#xff0c;我们对创建模式进行了介绍&#xff0c;并使用抽象工厂模式来创建对象族。 下一个模式是Factory模式 。 当涉及到Java时&#xff0c;工厂模式是最常用的模式之一。 那么&#xff0c;工厂模式到底是什么呢&#xff1f; 工厂模式处理创建对象而未指定确切的类或…

Java福尔摩斯的约会大侦探福尔摩斯接到一张奇怪的字条:“我们约会吧 3485djDkxh4hhGE 2984akDfkkkkggEdsb shgsfdk dHyscvnm”。大侦探很快就明白了

题目描述&#xff1a; 大侦探福尔摩斯接到一张奇怪的字条&#xff1a;“我们约会吧&#xff01; 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm”。大侦探很快就明白了&#xff0c;字条上奇怪的乱码实际上就是约会的时间“星期四 14:04”&#xff0c;因为前面…

Windows编程之网络之邮件槽通讯

第6节 使用邮件槽传输数据 网络通讯的理论很复杂&#xff0c;可是初学者不考虑性能的话&#xff0c;可以使用很简单的模式。一般而言网络通讯有两种模式&#xff0c;点对点模式或者广播模式。点对点模式就像一对一辅导&#xff0c;双方都能听清楚对方说什么&#xff0c;并作出…

java 批量处理 示例_Java异常处理教程(包含示例和最佳实践)

java 批量处理 示例异常是可能在程序执行期间发生的错误事件&#xff0c;它会破坏其正常流程。 Java提供了一种健壮且面向对象的方式来处理异常情况&#xff0c;称为Java异常处理 。 我们将在本教程中研究以下主题。 Java异常处理概述 异常处理关键字 异常层次 有用的异常方…

Java德才论宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之 小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若

题目描述&#xff1a; 宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”&#xff1a;“是故才德全尽谓之圣人&#xff0c;才德兼亡谓之愚人&#xff0c;德胜才谓之君子&#xff0c;才胜德谓之小人。凡取人之术&#xff0c;苟不得圣人&#xff0c;君子而与之&#xff0c…

Windows编程之多媒体

一、语音接口的使用: 第一步&#xff0c;安装MSSpeech SDK。 MSSpeech SDK可从网络课堂安装&#xff0c;也可在微软公司直接下载&#xff0c;安装完毕后具有了语音处理能力。 安装过程全选默认即可。 安装完毕后&#xff0c;在开始菜单中会增加MS Speech SDK 5.1&#xff0…

Java的@Serial批注

JDK可能正在使用JDK 11 &#xff1a; Serial获得另一个标准&#xff08;预定义&#xff09;注释 。 JDK-8202385 [“标记与序列相关的字段和方法的注释”]的目的是添加“某种“ SerialRelated”注释&#xff0c;以促进对序列字段和方法的声明的自动检查。” 这种想法是为了更好…

Java部分A+B正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6。现给定A、DA

题目描述&#xff1a; 正整数A的“DA&#xff08;为1位整数&#xff09;部分”定义为由A中所有DA组成的新整数PA。例如&#xff1a;给定A 3862767&#xff0c;DA 6&#xff0c;则A的“6部分”PA是66&#xff0c;因为A中有2个6。现给定A、DA、B、DB&#xff0c;请编写程序计算…

Windows编程之调用Matlab

一、选择matlab&#xff1a; 注意。Matlab的安装需要较长时间&#xff0c;建议本拓展在同学们自己的电脑上运行。 Matlab是大多数工科学生必修的科目&#xff0c;是一个口碑极佳的数学计算工具&#xff0c;可以支持立即运算和程序设计两种形式。Matlab较新的版本均提供32位版本…

JavaA除以B本题要求计算A/B,其中A是不超过1000位的正整数,B是1位正整数。你需要输出商数Q和余数R,使得A = B * Q + R成立。

题目描述&#xff1a; 本题要求计算A/B&#xff0c;其中A是不超过1000位的正整数&#xff0c;B是1位正整数。你需要输出商数Q和余数R&#xff0c;使得A B * Q R成立。 输入描述: 输入在1行中依次给出A和B&#xff0c;中间以1空格分隔。 输出描述: 在1行中依次输出Q和R&…

Windows编程之使用外部动态链接库——纸牌

C语言功能强大的一个重要原因是因为具有丰富的库函数&#xff0c;例如字符串处理有string库&#xff0c;数学处理有math库。微软公司对程序库的支持又更进一步&#xff0c;提供了丰富的动态链接库。下面以微软操作系统内嵌的纸牌链接库为例写一个简单的小程序。 由于我们已经较…

netbeans7.4_使用NetBeans 7.4 beta提示进行更好的基于JUnit的单元测试

netbeans7.4在上一篇文章中 &#xff0c;我写了NetBeans 7.4 beta中提供的提示 &#xff0c;这些提示提高了开发人员避免Java异常处理带来的讨厌的运行时问题的能力。 在本文中&#xff0c;我将探讨如何使用NetBeans 7.4 beta提供的另外两个提示使单元测试在执行单元测试期间更…

Java锤子剪刀布大家应该都会玩“锤子剪刀布”的游戏: 现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。

题目描述&#xff1a; 大家应该都会玩“锤子剪刀布”的游戏&#xff1a;现给出两人的交锋记录&#xff0c;请统计双方的胜、平、负次数&#xff0c;并且给出双方分别出什么手势的胜算最大。 输入描述: 输入第1行给出正整数N&#xff08;<105&#xff09;&#xff0c;即双方…

【MATLAB函数系列】fskmod函数参数及源代码详解

关注回复【fskmod】可看 在用matlab仿真生成fsk信号时&#xff0c;发现matlab库提供fskmod函数可以直接生成fsk信号&#xff0c;但生成的信号为复信号&#xff0c;于是查看其源码&#xff0c;结果对其原理看了好久都没明白&#xff0c;在网上查询资料也少得可怜&#xff0c;唯一…

Java数字黑洞给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到 一个新的数字。一直重复这样做,我们很快会停在有“数字

题目描述&#xff1a; 给定任一个各位数字不完全相同的4位正整数&#xff0c;如果我们先把4个数字按非递增排序&#xff0c;再按非递减排序&#xff0c;然后用第1个数字减第2个数字&#xff0c;将得到 一个新的数字。一直重复这样做&#xff0c;我们很快会停在有“数字黑洞”之…

Java Spring Security示例教程中的2种设置LDAP Active Directory身份验证的方法

LDAP身份验证是全球范围内最流行的企业应用程序身份验证机制之一&#xff0c;而Active Directory &#xff08;Microsoft针对Windows的LDAP实现&#xff09;是另一种广泛使用的LDAP服务器。 在许多项目中&#xff0c;我们需要通过登录屏幕中提供的凭据使用LDAP对活动目录进行身…

C语言文件读写操作之换行符处理

getc&#xff0c;fgetc&#xff1a; -1代表结束符&#xff0c;不但能接收键盘输入的内容&#xff0c;也能从文件中读取一个字符&#xff1b; getchar() 等价于 getc(stdin); putc,fputc: putchar© 等价于 putc(c,stdout); 文件操作 t模式 与 b模式&#xff1a; windo…

Java月饼月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需 求量,请你计算可以获得的最大收益是多少。注意:销售时允许取出一

题目描述&#xff1a; 月饼是中国人在中秋佳节时吃的一种传统食品&#xff0c;不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量&#xff0c;请你计算可以获得的最大收益是多少。 注意&#xff1a;销售时允许取出一部分库存。样例给出…