目录
- 背景
- 测试
- 环境
- 工具
- 说明
- 结果
- 结论
- 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:
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 Listlist; 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