对比ProtoBuf、JSON的序列化和反序列化能力

1.序列化能力对比验证

在这里让我们分别使用PB与JSON的序列化与反序列化能力,对值完全相同的一份结构化数据进行不同次数的性能测试。
为了可读性,下面这一份文本使用JSON格式展示了需要被进行测试的结构化数据内容:

 

开始进行测试代码编写,我们在新的目录下新建contacts. proto文件,内容如下:

 
  1. syntax="proto3";

  2. package compare_serialization;

  3. import "google/protobuf/any.proto"; // 引⼊ any.proto ⽂件

  4. // 地址

  5. message Address{

  6. string home_address = 1; // 家庭地址

  7. string unit_address = 2; // 单位地址

  8. }

  9. // 联系⼈

  10. message PeopleInfo {

  11. string name = 1; // 姓名

  12. int32 age = 2; // 年龄

  13. message Phone {

  14. string number = 1; // 电话号码

  15. enum PhoneType {

  16. MP = 0; // 移动电话

  17. TEL = 1; // 固定电话

  18. }

  19. PhoneType type = 2; // 类型

  20. }

  21. repeated Phone phone = 3; // 电话

  22. google.protobuf.Any data = 4;

  23. oneof other_contact { // 其他联系⽅式:多选⼀

  24. string qq = 5;

  25. string weixin = 6;

  26. }

  27. map<string, string> remark = 7; // 备注

  28. }

使用protoc命令编译文件后,新建性能测试文件compare.cc,我们分别对相同的结构化数据进行
100、1000、 10000 、100000 次的序列化与反序列化,分别获取其耗时与序列化后的大小。
内容如下:

 
  1. #include <iostream>

  2. #include <sys/time.h>

  3. #include <jsoncpp/json/json.h>

  4. #include "contacts.pb.h"

  5. using namespace std;

  6. using namespace compare_serialization;

  7. using namespace google::protobuf;

  8. #define TEST_COUNT 100000

  9. void createPeopleInfoFromPb(PeopleInfo *people_info_ptr);

  10. void createPeopleInfoFromJson(Json::Value& root);

  11. int main(int argc, char *argv[])

  12. {

  13. struct timeval t_start,t_end;

  14. double time_used;

  15. int count;

  16. string pb_str, json_str;

  17. // ------------------------------Protobuf 序列化------------------------------------

  18. {

  19. PeopleInfo pb_people;

  20. createPeopleInfoFromPb(&pb_people);

  21. count = TEST_COUNT;

  22. gettimeofday(&t_start, NULL);

  23. // 序列化count次

  24. while ((count--) > 0) {

  25. pb_people.SerializeToString(&pb_str);

  26. }

  27. gettimeofday(&t_end, NULL);

  28. time_used=1000000*(t_end.tv_sec - t_start.tv_sec) + t_end.tv_usec - t_start.tv_usec;

  29. cout << TEST_COUNT << "次 [pb序列化]耗时:" << time_used/1000 << "ms."

  30. << " 序列化后的大小:" << pb_str.length() << endl;

  31. }

  32. // ------------------------------Protobuf 反序列化------------------------------------

  33. {

  34. PeopleInfo pb_people;

  35. count = TEST_COUNT;

  36. gettimeofday(&t_start, NULL);

  37. // 反序列化count次

  38. while ((count--) > 0) {

  39. pb_people.ParseFromString(pb_str);

  40. }

  41. gettimeofday(&t_end, NULL);

  42. time_used=1000000*(t_end.tv_sec - t_start.tv_sec) + t_end.tv_usec - t_start.tv_usec;

  43. cout << TEST_COUNT << "次 [pb反序列化]耗时:" << time_used / 1000 << "ms." << endl;

  44. }

  45. // ------------------------------JSON 序列化------------------------------------

  46. {

  47. Json::Value json_people;

  48. createPeopleInfoFromJson(json_people);

  49. Json::StreamWriterBuilder builder;

  50. count = TEST_COUNT;

  51. gettimeofday(&t_start, NULL);

  52. // 序列化count次

  53. while ((count--) > 0) {

  54. json_str = Json::writeString(builder, json_people);

  55. }

  56. gettimeofday(&t_end, NULL);

  57. // 打印序列化结果

  58. // cout << "json: " << endl << json_str << endl;

  59. time_used=1000000*(t_end.tv_sec - t_start.tv_sec) + t_end.tv_usec - t_start.tv_usec;

  60. cout << TEST_COUNT << "次 [json序列化]耗时:" << time_used/1000 << "ms."

  61. << " 序列化后的大小:" << json_str.length() << endl;

  62. }

  63. // ------------------------------JSON 反序列化------------------------------------

  64. {

  65. Json::CharReaderBuilder builder;

  66. unique_ptr<Json::CharReader> reader(builder.newCharReader());

  67. Json::Value json_people;

  68. count = TEST_COUNT;

  69. gettimeofday(&t_start, NULL);

  70. // 反序列化count次

  71. while ((count--) > 0) {

  72. reader->parse(json_str.c_str(), json_str.c_str() + json_str.length(), &json_people, nullptr);

  73. }

  74. gettimeofday(&t_end, NULL);

  75. time_used=1000000*(t_end.tv_sec - t_start.tv_sec) + t_end.tv_usec - t_start.tv_usec;

  76. cout << TEST_COUNT << "次 [json反序列化]耗时:" << time_used/1000 << "ms." << endl;

  77. }

  78. return 0;

  79. }

  80. /**

  81. * 构造pb对象

  82. */

  83. void createPeopleInfoFromPb(PeopleInfo *people_info_ptr)

  84. {

  85. people_info_ptr->set_name("张珊");

  86. people_info_ptr->set_age(20);

  87. people_info_ptr->set_qq("95991122");

  88. for(int i = 0; i < 5; i++) {

  89. PeopleInfo_Phone* phone = people_info_ptr->add_phone();

  90. phone->set_number("110112119");

  91. phone->set_type(PeopleInfo_Phone_PhoneType::PeopleInfo_Phone_PhoneType_MP);

  92. }

  93. Address address;

  94. address.set_home_address("陕西省西安市长安区");

  95. address.set_unit_address("陕西省西安市雁塔区");

  96. google::protobuf::Any * data = people_info_ptr->mutable_data();

  97. data->PackFrom(address);

  98. people_info_ptr->mutable_remark()->insert({"key1", "value1"});

  99. people_info_ptr->mutable_remark()->insert({"key2", "value2"});

  100. people_info_ptr->mutable_remark()->insert({"key3", "value3"});

  101. people_info_ptr->mutable_remark()->insert({"key4", "value4"});

  102. people_info_ptr->mutable_remark()->insert({"key5", "value5"});

  103. }

  104. /**

  105. * 构造json对象

  106. */

  107. void createPeopleInfoFromJson(Json::Value& root) {

  108. root["name"] = "张珊";

  109. root["age"] = 20;

  110. root["qq"] = "95991122";

  111. for(int i = 0; i < 5; i++) {

  112. Json::Value phone;

  113. phone["number"] = "110112119";

  114. phone["type"] = 0;

  115. root["phone"].append(phone);

  116. }

  117. Json::Value address;

  118. address["home_address"] = "陕西省西安市长安区";

  119. address["unit_address"] = "陕西省西安市雁塔区";

  120. root["address"] = address;

  121. Json::Value remark;

  122. remark["key1"] = "value1";

  123. remark["key2"] = "value2";

  124. remark["key3"] = "value3";

  125. remark["key4"] = "value4";

  126. remark["key5"] = "value5";

  127. root["remark"] = remark;

  128. }

makefile:

 
  1. compare:*.cc

  2. g++ -o $@ $^ -std=c++11 -lprotobuf

  3. .PHONY:clean

  4. clean:

  5. rm -rf compare

测试结果如下:

100次 [pb序列化]耗时:0.382ms. 序列化后的大小:278
100次 [pb反序列化]耗时:0.442ms.
100次 [json序列化]耗时:2.43ms. 序列化后的大小:567
100次 [json反序列化]耗时:1.091ms.

1000次 [pb序列化]耗时:3.196ms. 序列化后的大小:278
1000次 [pb反序列化]耗时:5.047ms.
1000次 [json序列化]耗时:20.22ms. 序列化后的大小:567
1000次 [json反序列化]耗时:13.037ms.

10000次 [pb序列化]耗时:29.206ms. 序列化后的大小:278
10000次 [pb反序列化]耗时:48.03ms.
10000次 [json序列化]耗时:206.259ms. 序列化后的大小:567
10000次 [json反序列化]耗时:114.738ms.

由实验结果可得:
●编解码性能: ProtoBuf 的编码解码性能,比JSON高出2-4倍。
●内存占用: ProtoBuf的内存278,而JSON到达567, ProtoBuf的内存占用只有JSON的1/2。
注:以上结论的数据只是根据该项实验得出。因为受不同的字段类型、字段个数等影响,测出的数据会有所差异。

2.总结

小结:
1. XML、JSON、 ProtoBuf 都具有数据结构化和数据序列化的能力。
2. XML、JSON更注重数据结构化,关注可读性和语义表达能力。ProtoBuf 更注重数据序列化,关注效率、空间、速度,可读性差,语义表达能力不足,为保证极致的效率,会舍弃一部分元信息。
3. ProtoBuf 的应用场景更为明确,XML、JSON的应用场景更为丰富。




对比ProtoBuf和JSON的序列化和反序列化能力_protobuf和json区别-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值