博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java序列化/反序列化之xstream、protobuf、protostuff 的比较与使用例子
阅读量:6290 次
发布时间:2019-06-22

本文共 4268 字,大约阅读时间需要 14 分钟。

 

 

目录

  1. 背景
  2. 测试
    1. 环境
    2. 工具
    3. 说明
    4. 结果
    5. 结论
  3. xstream简单教程
    1. 准备
    2. 代码 
  4. protobuf简单教程
    1. 快速入门
      1. 下载.exe编译器
      2. 编写.proto文件
      3. 利用编译器编译.proto文件生成javabean
      4. 引用jar包
      5. 直接使用javabean自带的序列化、反序列化、提取属性等方法
  5. protostuff简单教程
    1. 快速入门
      1. 引用jar包
      2. 直接使用相关序列化、反序列化语法

 

1、背景

  项目中http通信离不开对象的序列化和反序列化,通过序列化技术,可以夸语言实现数据的传输,例如把一个对象序列化后的二进制数据、xml格式数据存在文本文件,下次通过读取文件,然后反序列化一下即可重新生成该对象,抑或通过网络把序列化后的数据传输到另一个终端,对方通过反序列化后也可以重新复制出一个大概相同的对象出来。

  在一般项目中,xml是一个不错的选择,例如微信公众平台的大多数接口,就是使用xml技术来序列化传输的,学习成本低,可读性高,方便调试,可以直接在浏览器查看结果等等都是他的优点,对于对速度要求不高的系统来说,的确是一种不错的选择。但如果系统对序列化效率要求很高,例如想比xml快上10倍?那么可能就得考虑换成其他技术了,例如——protobuf。

  protobuf是谷歌推出的与语言无关、平台无关的通信协议,一个对象经过protobuf序列化后将变成二进制格式的数据,所以他可读性差,但换来的是占用空间小,速度快。使用protobuf要先使用特定的语法编写一个.proto文件,该文件与语言无关,然后使用特殊的编译器对该文件进行编译,生成与语言相关的文件,如java,那么将生成java的类,该类不仅有我们自己定义的属性,还提供了序列化,反序列化等其他方法。直接把该类copy到项目中,就可以使用了。不过缺点是,假如我们是数据的发送方,那么接受方也要有一个通过相同的.proto编译出来的“类”(假设对方使用java语言),才可以顺利地进行反编译。这样一来,假如我们对proto 2.6版本的编辑器对.proto文件进行编译,而对方使用的是2.3版本的编译器进行编译,那么编译出来的类是不一样的,且两个版本互不兼容。所以两方的版本要保持一致。这么一来,假如一方升级,但没及时通知另一方,那么可能导致对方无法反序列化!这个缺点也是不小的。

  针对以上缺点,一个基于protobuf的产品——protostuff诞生了,protostuff不需要依赖.proto文件,他可以直接对普通的javabean进行序列化、反序列化的操作,而效率上甚至比protobuf还快,不过使用protostuff的话可不可以xstream那样自定义转换器,这个还没研究过,如果有人研究过得,不妨留下评论。

  所以针对这三种技术,做了以下简单的比较和介绍。如果大家觉得proto系列还可以的话,或者在以后的项目中,可以考虑使用。

 

2、测试

2.1 测试环境

xstraem版本:1.3.1

protobuf-java版本:3.0.0-alpha-2

java版本:1.7

-Xms2048m

-Xmx2048m

 

2.2 测试工具

用时: 控制台输出时间

CPU&内存: jconsole

文件大小: 文件属性

 

2.3 说明

测试中,xmlprotoBuf和protostuff三种测试所使用的JavaBean所拥有的字段类型相同、字段数量相同(约28个)、字段所附的值相同、都包含有一个List<String>字段,用List字段的size来控制JavaBean对象的大小。本次测试中size=100

 

2.4  结果

测试A:10000个对象

 

 

xstream

protobuf

protostuff

序列化

用时(ms)

2399

648

261

占用的CPU(%)

24.2

12.3

3.4

占用的内存(M)

154

235

92

每个文件大小(byte

2822

574

574

 

反序列化

用时(ms)

3378

167

224

占用CPU(%)

15.9

14.2

6.1

占用内存(M)

248

307

164

备注:10000个对象

 

测试B:25000个对象

 

xstream

protobuf

protostuff

序列化

用时(ms)

4161

767

293

占用的CPU(%)

31.2

14.6

4.7

占用的内存(M)

495

228

194

每个文件大小(byte

2822

574

574

 

反序列化

用时(ms)

6941

252

393

占用CPU(%)

31.9

21.9

8.1

占用内存(M)

411

382

348

备注:25000个对象

测试C:100000个对象

 

xstream

protobuf

protostuff

序列化

用时(ms)

12867

3070

704

占用的CPU(%)

42.5

44.9

22.3

占用的内存(M)

1098

1058

572

每个文件大小(byte

2822

574

574

 

反序列化

用时(ms)

24442

4540

1522

占用CPU(%)

38.8

68.2

24.1

占用内存(M)

2215

597

870

备注:50000个对象

引用最后一组数据的直方图:

2.5 结论

1、序列化:

  1.1、速度上:protostuff比protobuf快3倍左右,protobuf比xml快4-5倍,该倍数随着序列化对象的增加,基本保持不变。

  1.2、CPU上:protostuff占用最少,protobuf其次,xml最后。

  1.3、内存上:protostuff占用最少,protobuf其次,xml最后。

  1.4、生成文件大小:protostuff占用最少,protobuf其次,xml最后,前面两者是后者的1/4左右。

2、反序列化

  2.1、速度上:在反序列化对象数量较少的情况下,protobuf比protostuff快1/4左右,比xml快10+倍。但随着对象数量的增加,protobuf发生了速率明显变慢的情况!从而被protostuff赶超。

  2.2、CPU上:protostuff占用最少,protobuf其次,xml最后。

  2.3、内存上:protostuff占用最少,protobuf其次,xml最后。

3、总结

  在各个方面上,protostuff的优势非常面试,而protobuf也不弱,考虑用来代替xml。

 

3、xstream简单教程

3.1 准备

jar包:pom.xml:

com.thoughtworks.xstream
xstream
1.3.1

 3.2 代码

1、java bean:

1 package com.zjm.www.po;  2   3 import java.util.List; 4 5 /** 6 * 商品类 7 */ 8 public class Products { 9 10 private String s1; 11 private String s2; 12 private String s3; 13 private String s4; 14 private String s5; 15 private String s6; 16 private String s7; 17 private String s8; 18 private String s9; 19 20 private int i1; 21 private int i2; 22 private int i3; 23 private int i4; 24 private int i5; 25 private int i6; 26 private int i7; 27 private int i8; 28 private int i9; 29 30 private boolean b1; 31 private boolean b2; 32 private boolean b3; 33 private boolean b4; 34 private boolean b5; 35 private boolean b6; 36 private boolean b7; 37 private boolean b8; 38 private boolean b9; 39 40 private List
list; 41 42 public String getS1() { 43 return s1; 44 } 45 46 public void setS1(String s1) { 47 this.s1 = s1; 48 } 49 50 public String getS2() { 51 return s2; 52 } 53 54 public void setS2(String s2) { 55 this.s2 = s2; 56 } 57 58 public String getS3() { 59 return s3; 60 } 61 62 public void setS3(String s3) { 63 this.s3 = s3; 64 } 65 66 public String getS4() { 67 return s4; 68 } 69 70 public void setS4(String s4) { 71 this.s4 = s4; 72 } 73 74 public String getS5() { 75 return s5; 76 } 77 78 public void setS5(String s5) { 79 this.s5 = s5; 80 } 81 82 public String getS6() { 83 return s6; 84 } 85 86 public void setS6(String s6) { 87 this.s6 = s6; 88 } 89 90 public

转载地址:http://qykta.baihongyu.com/

你可能感兴趣的文章
iOS--环信集成并修改头像和昵称(需要自己的服务器)
查看>>
PHP版微信权限验证配置,音频文件下载,FFmpeg转码,上传OSS和删除转存服务器本地文件...
查看>>
教程前言 - 回归宣言
查看>>
PHP 7.1是否支持操作符重载?
查看>>
Vue.js 中v-for和v-if一起使用,来判断select中的option为选中项
查看>>
Java中AES加密解密以及签名校验
查看>>
定义内部类 继承 AsyncTask 来实现异步网络请求
查看>>
VC中怎么读取.txt文件
查看>>
如何清理mac系统垃圾
查看>>
企业中最佳虚拟机软件应用程序—Parallels Deskto
查看>>
Nginx配置文件详细说明
查看>>
怎么用Navicat Premium图标编辑器创建表
查看>>
Spring配置文件(2)配置方式
查看>>
MariaDB/Mysql 批量插入 批量更新
查看>>
ItelliJ IDEA开发工具使用—创建一个web项目
查看>>
solr-4.10.4部署到tomcat6
查看>>
切片键(Shard Keys)
查看>>
淘宝API-类目
查看>>
virtualbox 笔记
查看>>
Git 常用命令
查看>>