前言
最近学习了字节开源的json库sonic-cpp,号称其性能为rapidjson的2.5倍,于是决定并验证一下,并结合qt的开源库qt-material-widgets与qcustomplot可视化测试结果,主要内容包括:1,sonic-cpp与rapidjson的benchmark测试;2,通过网络执行耗时较长的任务的解决方案;3,利用qt-material-widgets与qcustomplot等开源库生成界面。工程整体与上一篇文章类似(利用c++实现基于rpc的远端服务器参数实时查询 - 掘金 (juejin.cn))。
一、基于benchmark的sonic-cpp与rapidjson的性能对比
sonic-cpp(github.com/bytedance/s… )有c++和go版本的,下载好后,里面包含sonic-cpp、rapidjson、cjson、simdjson、yyjson等多种json库的benchmark(github.com/google/benc… )测试代码,要求c++17及以上,里面用到了std::filesystem,需要添加依赖stdc++fs;sonic-cpp提供了一个set_arch_flags的cmake函数也需要用到,其它正常编译即可。这里只对比sonic-cpp和rapidjson,删除无用代码。sonic-cpp提供的数据集里有一些几十M的的json文件,电脑性比较差的话可能会直接卡死,测试的时候将这些数据集排除掉。测试结果如下,将前3列数据的解析结果通过网络发送到客户端。
从结果上看,所有的测试场景的decode和encode,基本上都是sonic-cpp快,原因可能是进行了向量化(SIMD)优化(www.infoq.cn/article/Exk… )吧,不懂。
二、rpc通信的一些问题
1、通过网络执行耗时较长的任务的解决方案
这里耗时较长是指,客户端发起测试请求,服务端开始benchmark测试,客户端一直等待服务端返回数据。看了一下,sonic-cpp与rapidjson的性能测试共耗时大概60多秒。一般是客户端先采用发起一次请求命令,服务端会返回一个任务id,然后客户端利用任务id间隔一小段时间不停的向服务端查询结果,直至成功或失败。由于服务端需要处理多个客户端请求,因此需要用任务id来区分。按照这种方法,定义pb结构如下:
syntax = "proto2";
option cc_generic_services = true;
enum StatusType{
FAIL = 0;
PROGESSING = 1;
FINISH = 2;
}
message BenchmarkJsonInfo {
required string testName = 1;
required uint32 testTime = 2;
required uint32 cpuTime = 3;
};
//生成任务
message BenchmarkJsonTaskRequest {
};
message BenchmarkJsonTaskResponse {
required int32 taskId = 1;
};
service BenchmarkJsonTaskService {
rpc BenchmarkJsonTask(BenchmarkJsonTaskRequest) returns (BenchmarkJsonTaskResponse);
};
//查询状态
message QueryBenchmarkStatusRequest {
required int32 taskId = 1;
};
message QueryBenchmarkStatusResponse {
required StatusType status = 1;
required string errInfo = 2;
repeated BenchmarkJsonInfo benchmarkJsonInfos = 3;
};
service QueryBenchmarkStatusService {
rpc QueryBenchmarkStatus(QueryBenchmarkStatusRequest) returns (QueryBenchmarkStatusResponse);
};
2、基于brpc的较大数据传输的数据帧拼接问题
这里服务端采用brpc实现,客户端是Windows无法使用brpc,因而采用libevent实现rpc客户端。测试数据大概有3000个字节,发现libevent分两次进入了读回调函数,因此需要拼接数据。按照brpc协议进行如下简单的拼接数据,第一次收到数据时,解析第4~8个字节获得总数据大小(注意&的优先级低于