Protobuffer和json 简单对比(java语言)
2016-03-23 12:05
453 查看
一,应用场景
广告行业多平台之间, 会用http协议以post的方式传递很多上下文信息. 大平台(兼有pc和mobile),比如阿里/百度/腾讯目前都以protobuffer作为数据交换格式. 我所知道的纯移动流量平台mongo和小米,采用的json. 不能明白他们做选择时的考量是什么, 所以对两者做了简单的对比测试(当然,不一定能解决自己的困惑).
二, 案例设计
1, 测试proto协议
3, 针对以上数据格式, 做三组测试:
a) 混合数据: 如上图, 属性中既有数字, 又有字符串.
b) 纯数字测试: 把上图中的字符属性注释掉. 普通java bean也做对应处理.
c) 纯字符测试: 把上图中的数字属性注释掉.
三, 测试编码
1, proto数据格式的序列化,反序列化以及序列化后文件大小. 代码为"混合数据"的代码. 三组测试只有属性不一样, 做相应的注释就好.
三,测试结果
1, 数字字符混合测试
混合测试结果
2, 纯数字测试
纯数字测试
3, 纯字符
纯字符测试
四, 总结
1. 测试代码每次运行虽有细微差异, 但总的来说protobuff先性能和序列化后文件大小方面表现还不错, 尤其是文件大小, 比较适合我的应用场景. 跨网传输数据就能节约不少成本. 当然, json也有自己的优势, 不是protobuff能完全取代的, 具体得看应用场景.
2. pb对数字类型的编码压缩很大, 在做proto协议涉及时可以适当考虑这一点. 当然会牺牲一些cpu时间.
3. 听说"pb对嵌套数组类型会消耗大量内存", 未经测试验证.
4. 以上测试很简单, 仅供参考.
五, 参考资料
1. Protobuffer和json深度对比.
2. 序列化的几种方式
广告行业多平台之间, 会用http协议以post的方式传递很多上下文信息. 大平台(兼有pc和mobile),比如阿里/百度/腾讯目前都以protobuffer作为数据交换格式. 我所知道的纯移动流量平台mongo和小米,采用的json. 不能明白他们做选择时的考量是什么, 所以对两者做了简单的对比测试(当然,不一定能解决自己的困惑).
二, 案例设计
1, 测试proto协议
message Teacher{ required int32 id = 1; required string name = 2; //学生列表 repeated Student students = 3; } message Student { required int32 id = 1; required string name = 2; optional string desc = 3; }2, 最近基本的java bean 类Teacher和Student, 属性和proto里的数据完全一致.
3, 针对以上数据格式, 做三组测试:
a) 混合数据: 如上图, 属性中既有数字, 又有字符串.
b) 纯数字测试: 把上图中的字符属性注释掉. 普通java bean也做对应处理.
c) 纯字符测试: 把上图中的数字属性注释掉.
三, 测试编码
1, proto数据格式的序列化,反序列化以及序列化后文件大小. 代码为"混合数据"的代码. 三组测试只有属性不一样, 做相应的注释就好.
@Test public void protoSerialization() { User.Teacher.Builder teacher = User.Teacher.newBuilder(); teacher.setId(100); teacher.setName("刘备"); User.Student.Builder student; for(int i=0;i<size;i++){ student = User.Student.newBuilder(); student.setId(101+i); student.setName("赵云"); student.setDesc("五虎将之一"); teacher.addStudents(student.build()); } List<byte[]> listB = new ArrayList<>(); long start = System.currentTimeMillis(); for(User.Student.Builder s:teacher.getStudentsBuilderList()){ listB.add(s.build().toByteArray()); } System.out.println("protobuffer序列化耗时:"+(System.currentTimeMillis() - start)); start = System.currentTimeMillis(); for(byte[] b:listB){ try { User.Student.parseFrom(b); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } System.out.println("protobuffer反序列化耗时:"+(System.currentTimeMillis() - start)); try { FileOutputStream fileOutputStream = new FileOutputStream("E:\\temp\\teacher-proto.txt"); fileOutputStream.write(teacher.build().toByteArray()); // teacher.build().writeTo(fileOutputStream); fileOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } }2. 阿里巴巴的fastjson工具包操作json的测试代码. 由于使用静态方法操作, 所以在junit的setUp()方法中预先加载了JSON类.
@Test public void fastJsonSerialization(){ Teacher teacher = new Teacher(); teacher.setId(100); teacher.setName("刘备"); Student student = null; List<Student> students = new ArrayList<>(); for(int i=0;i<size;i++){ student = new Student(); student.setId(101+i); student.setName("赵云"); student.setDesc("五虎将之一"); students.add(student); } List<String> jsonStr = new ArrayList<>(); long start = System.currentTimeMillis(); for(Student s:students){ jsonStr.add(JSON.toJSONString(s)); } System.out.println("fastJson序列化耗时:"+(System.currentTimeMillis() - start)); start = System.currentTimeMillis(); for(String str:jsonStr){ JSON.parseObject(str, Student.class); } System.out.println("fastJson反序列化耗时:"+(System.currentTimeMillis() - start)); teacher.setStudents(students); String result = JSON.toJSONString(teacher); try { FileWriter file = new FileWriter("E:\\temp\\teacher-fast-json.txt"); file.write(result); file.close(); } catch (IOException e) { e.printStackTrace(); } }3. google 的json工具包操作json的测试代码
<span style="white-space:pre"> </span>@Test public void gJsonSerialization(){ Teacher teacher = new Teacher(); teacher.setId(100); teacher.setName("刘备"); Student student = null; List<Student> students = new ArrayList<>(); for(int i=0;i<size;i++){ student = new Student(); student.setId(101+i); student.setName("赵云"); student.setDesc("五虎将之一"); students.add(student); } List<String> jsonStr = new ArrayList<>(); Gson g = new Gson(); long start = System.currentTimeMillis(); for(Student s:students){ jsonStr.add(g.toJson(s)); } System.out.println("gson序列化耗时:"+(System.currentTimeMillis() - start)); start = System.currentTimeMillis(); for(String str:jsonStr){ g.fromJson(str, Student.class); } System.out.println("gson反序列化耗时:"+(System.currentTimeMillis() - start)); teacher.setStudents(students); String result = new Gson().toJson(teacher); try { FileWriter file = new FileWriter("E:\\temp\\teacher-gson.txt"); file.write(result); file.close(); } catch (IOException e) { e.printStackTrace(); } }
三,测试结果
1, 数字字符混合测试
数据格式 | 序列化耗时(ms) | 反序列化耗时(ms) | 文件大小 |
---|---|---|---|
protobuffer | 61 | 20 | 440k |
fastjson工具处理json | 64 | 60 | 781k |
gson处理json | 112 | 115 | 781k |
数据格式 | 序列化耗时(ms) | 反序列化耗时(ms) | 文件大小 |
---|---|---|---|
protobuffer | 30 | 24 | 74k |
fastjson工具处理json | 43 | 48 | 180k |
gson处理json | 63 | 106 | 180k |
数据格式 | 序列化耗时(ms) | 反序列化耗时(ms) | 文件大小 |
---|---|---|---|
protobuffer | 57 | 19 | 396k |
fastjson工具处理json | 45 | 62 | 630 |
gson处理json | 96 | 95 | 630 |
1. 测试代码每次运行虽有细微差异, 但总的来说protobuff先性能和序列化后文件大小方面表现还不错, 尤其是文件大小, 比较适合我的应用场景. 跨网传输数据就能节约不少成本. 当然, json也有自己的优势, 不是protobuff能完全取代的, 具体得看应用场景.
2. pb对数字类型的编码压缩很大, 在做proto协议涉及时可以适当考虑这一点. 当然会牺牲一些cpu时间.
3. 听说"pb对嵌套数组类型会消耗大量内存", 未经测试验证.
4. 以上测试很简单, 仅供参考.
五, 参考资料
1. Protobuffer和json深度对比.
2. 序列化的几种方式
相关文章推荐
- React-native Android 环境配置
- Html.Action用法
- js一百零一夜之第十三夜-javascript 数组元素的删除
- XML数据解析方式各有什么不同,JSON解析有哪些框架?
- js 实现页面时间与当前时间同步
- HTML5图片上传预览
- JavaScript弹出对话框的三种方式
- 使用Gson轻松解决复杂结构的Json数据解析
- html中offsetTop、clientTop、scrollTop、offsetTop各属性介绍(转载)
- jquery来制作动态加载树
- node js官网下载地址
- jQuery复习:第二章&第三章
- JSON
- Css3之高级-1 Css复杂选择器(兄弟选择器 、属性选择器、伪类选择器、伪元素选择器)
- jQuery写的一棵动态加载的树
- HTML标签整理
- JS Replace 全部替换字符用法
- 解析json字符串,并且获取其中某个key的值
- JS随机洗牌算法之数组随机排序
- React-开发工具