前言
本篇对cjson,rapidjson,yyjson三种json反序列化工具的性能进行对比。
有json样本数据如下:
实验环境:
cpu:Xeon
cpu主频:2.20GHz
以下示例均未对字段的安全性进行检测。各示例的字段安全性检查参考json系列第一篇“cjson,rapidjson,yyjson解析示例”。
一、cjson反序列化性能
1 #include<stdio.h> 2 #include<sys/time.h> 3 4 #include"cJSON.h" 5 6 // g++ -g -o cjson_speed_test -std=c++11 cjson_speed_test.c cJSON.c 7 8 int main() 9 { 10 int cnt = 0; 11 timeval st, et; 12 13 cJSON *json_root; 14 char str_buf[1024] = "{\"uri\":\"/uriCSh56j30cbGa\",\"host\":\"www.baidu.com\",\"uagent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64\",\"accept\":\"*/*\",\"method\":\"GET\",\"date\":\"Mon, 12 Jul 21 10:35:26 GMT\",\"resp_content_type\":\"video/fli\",\"status\":200,\"resp_content_length\":20480,\"timestamp\":\"2021-07-12T02:38:13.074829000\",\"traffic_id\":1057153235624398,\"protocol\":\"http\",\"src_ip\":\"112.1.101.40\",\"src_port\":22291,\"dst_ip\":\"112.2.81.190\",\"dst_port\":80,\"random_code\":7449212903698783717,\"feature_code\":\"y0BMEwnJ7RFICUAC5FKYkStTLVw=\"}"; 15 16 gettimeofday(&st, NULL); 17 while(1) { 18 json_root = cJSON_Parse(str_buf); 19 20 cJSON_GetObjectItem(json_root, "protocol"); 21 cJSON_GetObjectItem(json_root, "uri"); 22 23 cJSON_GetObjectItem(json_root, "host"); 24 cJSON_GetObjectItem(json_root, "uagent"); 25 26 cJSON_GetObjectItem(json_root, "src_port"); 27 cJSON_GetObjectItem(json_root, "dst_port"); 28 29 cJSON_GetObjectItem(json_root, "timestamp"); 30 cJSON_GetObjectItem(json_root, "feature_code"); 31 32 cJSON_GetObjectItem(json_root, "src_ip"); 33 cJSON_GetObjectItem(json_root, "dst_ip"); 34 35 cJSON_GetObjectItem(json_root, "traffic_id"); 36 cJSON_GetObjectItem(json_root, "random_code"); 37 38 cJSON_Delete(json_root); 39 40 cnt++; 41 gettimeofday(&et, NULL); 42 if(et.tv_sec - st.tv_sec >= 10) { 43 break; 44 } 45 } 46 47 printf("deserialization per second:%d\n", cnt/10); 48 return 0; 49 }
反序列化性能:
二、rapidjson反序列化性能
rapidjson有两种解析方法,一种是Parse,另一种是ParseInsitu(原位解析)。区别在于ParseInsitu不需要进行malloc操作,在原来的字符串空间中进行字符串反序列化,弊端是原来的字符串会被修改。这里选用Parse方法。
1 #include<stdio.h> 2 #include<sys/time.h> 3 4 #include "rapidjson/rapidjson.h" 5 #include "rapidjson/document.h" 6 #include "rapidjson/stringbuffer.h" 7 #include "rapidjson/writer.h" 8 9 // g++ -g -o rapidjson_speed_test -std=c++11 rapidjson_speed_test.c 10 11 int main() 12 { 13 int cnt = 0; 14 timeval st, et; 15 16 char str_buf[1024] = "{\"uri\":\"/uriCSh56j30cbGa\",\"host\":\"www.baidu.com\",\"uagent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64\",\"accept\":\"*/*\",\"method\":\"GET\",\"date\":\"Mon, 12 Jul 21 10:35:26 GMT\",\"resp_content_type\":\"video/fli\",\"status\":200,\"resp_content_length\":20480,\"timestamp\":\"2021-07-12T02:38:13.074829000\",\"traffic_id\":1057153235624398,\"protocol\":\"http\",\"src_ip\":\"112.1.101.40\",\"src_port\":22291,\"dst_ip\":\"112.2.81.190\",\"dst_port\":80,\"random_code\":7449212903698783717,\"feature_code\":\"y0BMEwnJ7RFICUAC5FKYkStTLVw=\"}"; 17 char str_buf_tmp[1024] = {0}; 18 19 rapidjson::Document parse_doc; 20 21 gettimeofday(&st, NULL); 22 while(1) { 23 24 parse_doc.Parse(str_buf); 25 parse_doc.FindMember("protocol")->value.GetString(); 26 parse_doc.FindMember("uri")->value.GetString(); 27 28 parse_doc.FindMember("host")->value.GetString(); 29 parse_doc.FindMember("resp_content_type")->value.GetString(); 30 31 parse_doc.FindMember("src_port")->value.GetInt(); 32 parse_doc.FindMember("dst_port")->value.GetInt(); 33 34 parse_doc.FindMember("timestamp")->value.GetString(); 35 parse_doc.FindMember("feature_code")->value.GetString(); 36 37 parse_doc.FindMember("src_ip")->value.GetString(); 38 parse_doc.FindMember("dst_ip")->value.GetString(); 39 40 parse_doc.FindMember("traffic_id")->value.GetUint64(); 41 parse_doc.FindMember("random_code")->value.GetUint64(); 42 43 cnt++; 44 gettimeofday(&et, NULL); 45 if(et.tv_sec - st.tv_sec >= 10) { 46 break; 47 } 48 } 49 50 printf("deserialization per second:%d\n", cnt/10); 51 return 0; 52 }
反序列化性能:
三、yyjson反序列化性能
1 #include<stdio.h> 2 #include<sys/time.h> 3 4 #include "yyjson.h" 5 6 // g++ -g -o yyjson_speed_test -std=c++11 yyjson_speed_test.c yyjson.c 7 8 int main() 9 { 10 int cnt = 0; 11 timeval st, et; 12 13 long value2; 14 char str_buf[1024] = "{\"uri\":\"/uriCSh56j30cbGa\",\"host\":\"www.baidu.com\",\"uagent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64\",\"accept\":\"*/*\",\"method\":\"GET\",\"date\":\"Mon, 12 Jul 21 10:35:26 GMT\",\"resp_content_type\":\"video/fli\",\"status\":200,\"resp_content_length\":20480,\"timestamp\":\"2021-07-12T02:38:13.074829000\",\"traffic_id\":1057153235624398,\"protocol\":\"http\",\"src_ip\":\"112.1.101.40\",\"src_port\":22291,\"dst_ip\":\"112.2.81.190\",\"dst_port\":80,\"random_code\":7449212903698783717,\"feature_code\":\"y0BMEwnJ7RFICUAC5FKYkStTLVw=\"}"; 15 16 gettimeofday(&st, NULL); 17 while(1) { 18 19 yyjson_doc *doc = yyjson_read(str_buf, strlen(str_buf), 0); 20 yyjson_val *root = yyjson_doc_get_root(doc); 21 22 yyjson_get_str(yyjson_obj_get(root, "protocol")); 23 yyjson_get_str(yyjson_obj_get(root, "uri")); 24 25 yyjson_get_str(yyjson_obj_get(root, "host")); 26 yyjson_get_str(yyjson_obj_get(root, "uagent")); 27 28 yyjson_get_int(yyjson_obj_get(root, "src_port")); 29 yyjson_get_int(yyjson_obj_get(root, "dst_port")); 30 31 yyjson_get_str(yyjson_obj_get(root, "timestamp")); 32 yyjson_get_str(yyjson_obj_get(root, "feature_code")); 33 34 yyjson_get_str(yyjson_obj_get(root, "src_ip")); 35 yyjson_get_str(yyjson_obj_get(root, "dst_ip")); 36 37 yyjson_get_uint(yyjson_obj_get(root, "traffic_id")); 38 yyjson_get_uint(yyjson_obj_get(root, "random_code")); 39 40 yyjson_doc_free(doc); 41 42 cnt++; 43 gettimeofday(&et, NULL); 44 if(et.tv_sec - st.tv_sec >= 10) { 45 break; 46 } 47 } 48 49 printf("deserialization per second:%d\n", cnt/10); 50 return 0; 51 }
反序列化性能:
四、结论
yyjson的反序列化性能真是让我感到欣喜,是cjson三倍以上、rapidjson Parse方法的10倍以上。若编译添加-O2优化参数,yyjson的测试结果更加惊喜,并且yyjson的cpu使用率更低。
另外,yyjson的序列化性能也是三者中最高的。
推荐大家使用yyjson!