最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

別再推薦使用jsoncpp了!

2022-11-27 23:02 作者:L__B_  | 我要投稿

事件起因

今天刷視頻看到一位up寫的json解析庫的性能超群,秒殺了一眾json解析庫,其中包括我比較喜歡的?nlohmann json?庫,這個庫在他的測試中性能墊底,我曾寫過一個json解析庫,性能的對比對象就是這個庫,我記得是略有不如。所以我第一時間想到的是不是測試有問題,nlohmann json?不可能這么慢啊,明明用到了大量模板的魔法??,然后我就親自把?nlohmann json?和?jsoncpp?以及他的庫都測了一遍。


為什么不推薦jsoncpp

如果有用過?jsoncpp?的,以及其他語言的json庫的,我覺得都會認為?jsoncpp?的api也太難用了吧。。。

但是如果這一切都是為了性能,那么還是有選擇余地的,但如果?jsoncpp?的復雜并沒有帶來實質(zhì)性的性能提升,那么我們?yōu)槭裁床挥酶唵魏糜眯阅芤哺训?nlohmann json?呢?

以下為測試源碼:Timer類用于計時

#include "time.hpp"
#include <iostream>
#include <filesystem>
#include <fstream>
using namespace std;
#include "nlohmann/json.hpp"
using json_nl = nlohmann::json;

#include"json/json.h"
using Value = Json::Value;
using Reader = Json::Reader;

#include "Json.h"

#include "my-json/Parser.h"
using my_parser = json::Parser;

//用于調(diào)整測試和驗證文件的路徑
#define BASE_DIR ?"../../"

//輸出到valid.json文件方便查看驗證是否解析正確
void outPutValidJson(std::string const& src){
 ?auto ofs = ofstream(BASE_DIR"valid.json");
 ?ofs<<src;
}

//獲取用于測試的json數(shù)據(jù)
std::string getSourceString(){
 ?auto ifs = ifstream(BASE_DIR"test.json");
 ?if(ifs){
 ? ?return string{istreambuf_iterator<char>(ifs),istreambuf_iterator<char>()};
 ?}
 ?return {};
}

//測試yaziJson的表現(xiàn)
void testYaziJson()
{
 ?//get src string
 ?auto data = getSourceString();
 ?yazi::json::Json json;
 ?//start bench
 ?{
 ? ?Timer t;
 ? ?json.parse(data);
 ?}
 ?//valid string
 ?outPutValidJson(json.str());
}

//測試nlohmannJson的表現(xiàn)
void testNlohmannJson()
{
 ? //get src string
 ?auto data = getSourceString();
 ?json_nl j;
 ?//start bench
 ?{
 ? ?Timer t;
 ? ?j = std::move(json_nl::parse(data));
 ?}
 ?//valid string
 ?outPutValidJson(j.dump());
}

//測試jsoncpp的表現(xiàn)
void testJsonCpp(){
 ?//get src string
 ?auto data = getSourceString();
 ?Value j;
 ?Reader r;
 ?//start bench
 ?{
 ? ?Timer t;
 ? ?if(!r.parse(data,j)){
 ? ? ?std::cerr<<"jsoncpp 出錯";
 ? ? ?return;
 ? ?}
 ?}
 ?//valid string
 ?outPutValidJson(j.toStyledString());
}

//測試我的json解析庫的表現(xiàn)
void testMyJson(){
 ? ?//get src string
 ?auto data = getSourceString();
 ?json::JObject j;
 ?//start bench
 ?{
 ? ?Timer t;
 ? ?j = std::move(my_parser::FromString(data));
 ?}
 ?//valid string
 ?outPutValidJson(j.to_string());
}

int main()
{

 ?for(int i=0;i<10;i++){
 ? ?testYaziJson();
 ? ?testMyJson();
 ? ?testJsonCpp();
 ? ?testNlohmannJson();
 ? ?std::cout<<"-----------------------"<<std::endl;
 ?}

}

代碼倉庫:https://github.com/ACking-you/bench_json4cpp

平均10次結(jié)果:

yazi-json: 482 us (0.482000 ms)?

my-json: 518 us (0.518000 ms)?

json-cpp: 1046 us (1.046000 ms)?

nlohmann-json: 884 us (0.884000 ms)

up寫的那個庫確實是最快的,但是最慢的不是?nlohmann json, 而是?jsoncpp。而且差距也沒有up視頻里面那么大,兩倍的差距而已,這對于一個淺拷貝和深拷貝的性能差距是很正常的。我估計他那里測試的時候沒開 release 優(yōu)化(對應 g++ -o3 優(yōu)化,看了源碼,果然大佬是直接寫 makefile 里面的 flag 用的 -o2 優(yōu)化),那么他視頻里的性能差距就很正常了,因為在沒開 release 優(yōu)化的前提下,某個庫如果大量用到 STL 以及元模板編程的時候,STL 會拖后腿,而元模板也沒法發(fā)揮最大效用。所以最終用于生產(chǎn)開 release 是很有必要的。

舉個簡單的例子:在大家的印象中 make_unique 或 make_shared 創(chuàng)建智能指針會優(yōu)化減少一次拷貝,那么相比直接 new 對象性能肯定會更好,你可以試試,實際測試中如果是 debug 情況下,直接 new 大概率會更快,但是切到 release 模式兩者效率都有進步,但 make 系列函數(shù)調(diào)用的優(yōu)化會更多。

json解析如何優(yōu)化性能

C++ json解析的性能瓶頸就在于?std::string?等STL容器默認的拷貝行為,一個簡單粗暴的優(yōu)化方式就是通過傳指針的方式而不是傳值的方式,但是這樣外界就需要來管理內(nèi)存了,否則會產(chǎn)生內(nèi)存泄漏等問題。前面那個大佬寫的庫處理方式就是這樣的。

熟悉cpp的朋友,大概率想到避免拷貝的方式就是移動,只要強制對象只能移動不能拷貝就行了。

洞察我之前寫的json解析庫,發(fā)現(xiàn)還有一個地方經(jīng)常需要拷貝,而且還沒法避免。string 類型的substr方法,所以我換成了string_view。這樣在內(nèi)部使用的內(nèi)存和外界就一致了,這就需要用戶確保這個內(nèi)存不會被修改或回收。傳入字符串進行解析很明顯不應該擁有所有權,即便擁有也應該把外界的內(nèi)存移動進來,所以采取string_view則是不擁有所有權的方式優(yōu)化。同時還有個好處就是兼容了C-style字符串。

具體實現(xiàn)代碼:https://github.com/ACking-you/bench_json4cpp/tree/master/my-json


別再推薦使用jsoncpp了!的評論 (共 條)

分享到微博請遵守國家法律
藁城市| 乌拉特中旗| 定远县| 恭城| 新河县| 射阳县| 黄梅县| 大余县| 泉州市| 德钦县| 墨脱县| 西乌| 新田县| 景谷| 广宁县| 沧州市| 黔东| 海林市| 饶河县| 刚察县| 南开区| 扎赉特旗| 大安市| 滦南县| 虞城县| 潼关县| 洞头县| 晋州市| 临沧市| 衡山县| 富裕县| 双牌县| 公主岭市| 仪征市| 合作市| 紫金县| 杭锦后旗| 利辛县| SHOW| 论坛| 微山县|