上一篇文章 通讯协议序列化解读(一):http://www.cnblogs.com/tohxyblog/p/8974641.html 

前言:上一面文章我们介绍了java序列化,以及谷歌protobuf,但是由于protobuf的使用起来并不像其他序列化那么简单(首先要写.proto文件,然后编译.proto文件,生成对应的.java文件),所以即使他是如何的优秀,也还是没能抢占json的份额。
这篇文章我们要介绍的是一款基于protobuf的java序列化协议——prorostuff,在java端能极大的简便使用,而且反序列化可由protobuf完成(那么前端就可以用其他语言的protobuf解码)。

一、protostuff介绍

protostuff 基于Google protobuf,但是提供了更多的功能和更简易的用法。其中,protostuff-runtime 实现了无需预编译对java bean进行protobuf序列化/反序列化的能力。protostuff-runtime的局限是序列化前需预先传入schema,反序列化不负责对象的创建只负责复制,因而必须提供默认构造函数。此外,protostuff 还可以按照protobuf的配置序列化成json/yaml/xml等格式。

在性能上,protostuff不输原生的protobuf,甚至有反超之势。

二、Protostuff特征

  1. 支持protostuff-compiler产生的消息

  2. 支持现有的POJO

  3. 支持现有的protoc产生的Java消息

  4. 与各种移动平台的互操作能力(Android、Kindle、j2me)

  5. 支持转码

三、工具类实现

导包:

<!-- //protostuff序列化 -->
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.0.8</version>
</dependency>
<!-- Objenesis -->
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>2.1</version>
</dependency>

工具类:

package com.result.base.tools;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd; import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema; /**
* @author 作者 huangxinyu
* @version 创建时间:2018年1月9日 下午7:41:24
* Protostuff序列化工具
*/
public class SerializationUtil {
private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>(); private static Objenesis objenesis = new ObjenesisStd(true); private SerializationUtil() {
} @SuppressWarnings("unchecked")
private static <T> Schema<T> getSchema(Class<T> cls) {
Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
if (schema != null) {
cachedSchema.put(cls, schema);
}
}
return schema;
} @SuppressWarnings("unchecked")
public static <T> String serializeToString(T obj) {
Class<T> cls = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(cls);
return new String(ProtobufIOUtil.toByteArray(obj, schema, buffer), "ISO8859-1");
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
} public static <T> T deserializeFromString(String data, Class<T> cls) {
try {
T message = (T) objenesis.newInstance(cls);
Schema<T> schema = getSchema(cls);
ProtobufIOUtil.mergeFrom(data.getBytes("ISO8859-1"), message, schema);
return message;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
} @SuppressWarnings("unchecked")
public static <T> byte[] serializeToByte(T obj) {
Class<T> cls = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(cls);
return ProtobufIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
} public static <T> T deserializeFromByte(byte[] data, Class<T> cls) {
try {
T message = (T) objenesis.newInstance(cls);
Schema<T> schema = getSchema(cls);
ProtobufIOUtil.mergeFrom(data, message, schema);
return message;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}

  

四、性能测试

4.1 测试环境

xstraem版本:1.3.1

protobuf-java版本:3.0.0-alpha-2

java版本:1.7

-Xms2048m

-Xmx2048m

4.2 测试工具

用时: 控制台输出时间

CPU&内存: jconsole

文件大小: 文件属性

4.3 说明

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

4.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个对象

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

4.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。

通讯协议序列化解读(二) protostuff详解教程的更多相关文章

  1. 通讯协议序列化解读(一) Protobuf详解教程

    前言:说到JSON可能大家很熟悉,是目前应用最广泛的一种序列化格式,它使用起来简单方便,而且拥有超高的可读性.但是在越来越多的应用场景里,JSON冗长的缺点导致它并不是一种最优的选择. 一.常用序列化 ...

  2. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  3. 搞懂分布式技术4:ZAB协议概述与选主流程详解

    搞懂分布式技术4:ZAB协议概述与选主流程详解 ZAB协议 ZAB(Zookeeper Atomic Broadcast)协议是专门为zookeeper实现分布式协调功能而设计.zookeeper主要 ...

  4. ViewPager 详解(二)---详解四大函数

    前言:上篇中我们讲解了如何快速实现了一个滑动页面,但问题在于,PageAdapter必须要重写的四个函数,它们都各有什么意义,在上节的函数内部为什么要这么实现,下面我们就结合Android的API说明 ...

  5. 转载 C# 序列化与反序列化意义详解

    C# 序列化与反序列化意义详解 总结: ①序列化基本是指把一个对象保存到文件或流中,比如可以把文件序列化以保存到Xml中,或一个磁盘文件中②序列化以某种存储形式使自定义对象持久化: ③将对象从一个地方 ...

  6. HTTP协议头部与Keep-Alive模式详解

    HTTP协议头部与Keep-Alive模式详解 .什么是Keep-Alive模式? 我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器 ...

  7. iOS 开发之照片框架详解之二 —— PhotoKit 详解(下)

    本文链接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 这里接着前文<iOS ...

  8. iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)

    转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html 一. 概况 本文接着 iOS 开 ...

  9. Hexo系列(二) 配置文件详解

    Hexo 是一款优秀的博客框架,在使用 Hexo 搭建一个属于自己的博客网站后,我们还需要对其进行配置,使得 Hexo 更能满足自己的需求 这里所说的配置文件,是位于站点根目录下的 _config.y ...

随机推荐

  1. SpringMVC(四):@RequestMapping结合org.springframework.web.filter.HiddenHttpMethodFilter实现REST请求

    1)REST具体表现: --- /account/1  HTTP GET       获取id=1的account --- /account/1  HTTP DELETE 删除id=1的account ...

  2. POJ-3026 Borg Maze---BFS预处理+最小生成树

    题目链接: https://vjudge.net/problem/POJ-3026 题目大意: 在一个y行 x列的迷宫中,有可行走的通路空格' ',不可行走的墙'#',还有两种英文字母A和S,现在从S ...

  3. Batch训练的反向传播过程

    Batch训练的反向传播过程 本文试图通过Softmax理解Batch训练的反向传播过程 采用的网络包含一层全连接和一层softmax,具体网络如下图所示: 交叉熵成本函数: \[L = - \fra ...

  4. Java集合框架知多少——干货!!!

    Java集合框架的组成 注意:四个接口的区别 ① Collection:存储无序的.不唯一的数据: ② List:存储有序的.不唯一的数据: ③ Set:存储无序的.唯一的数据: ④ Map:以键值对 ...

  5. C# 关键字替换

    /// <summary> /// 关键字替换 /// </summary> /// <param name="body"></param ...

  6. 【bzoj4009 hnoi2015】接水果

    题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更加难的版本. 首先有 ...

  7. ●BZOJ 3879 SvT

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3879 题解: 后缀数组,单调栈,RMQ 其实类似 BZOJ 3238 [Ahoi2013]差 ...

  8. hdu3340 线段树+多边形

    Rain in ACStar Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  9. POJ2187Beauty Contest 旋转卡壳

    题目链接 http://poj.org/problem?id=2187 先求凸包 再求凸多边形直径 旋转卡壳模板题 #include<cstdio> #include<cstring ...

  10. (转)Linux下C++开发初探

    1.开发工具 Windows下,开发工具多以集成开发环境IDE的形式展现给最终用户.例如,VS2008集成了编辑器,宏汇编ml,C /C++编译器cl,资源编译器rc,调试器,文档生成工具, nmak ...