目录
- 背景
- 测试
- 环境
- 工具
- 说明
- 结果
- 结论
- xstream简单教程
- 准备
- 代码
- protobuf简单教程
- 快速入门
- 下载.exe编译器
- 编写.proto文件
- 利用编译器编译.proto文件生成javabean
- 引用jar包
- 直接使用javabean自带的序列化、反序列化、提取属性等方法
- 快速入门
- protostuff简单教程
- 快速入门
- 引用jar包
- 直接使用相关序列化、反序列化语法
- 快速入门
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 说明
测试中,xml和protoBuf和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:
<!-- xstream -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
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<String> 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