厝,Simdjson:一个超高速的JSON解析东西,蝌蚪

JSON文档在Internet上厝,Simdjson:一个超高速的JSON解析东西,蝌蚪无处不在,效劳器花费很多时刻来解析这些文档。咱们期望在进行彻底验证(包括字符编码)时尽或许运用常用的SIMD指令来加快JSON自身的解析。

体现成果

simdjson运用的指令比最先进的解析器RapidJSON少四分之三,比sajson少百分之五十。据咱们所知,simdjson是第一个在商用处理器上以每秒千兆字节运转的彻底验证的JSON解析器。

在Skylake处理器上,twitter.json文件上各种处理器的解析速度(以GB / s为单位)如下。

解析器 GB /秒 simdjson 2.2 RapidJSON编码验证 0.51 RapidJSON编码验证,原位 0.71 sajson(原状,动态) 0.70 sajson(insitu,static) 0.97 dropbox 0.14 F厝,Simdjson:一个超高速的JSON解析东西,蝌蚪ASTJSON 0.26 gason 0.85 ultrajson 0.42 jsmn 0.28 cJSON 0.34 要求

努波顿的破釜沉舟 颜丹晨老公陈昊

咱们经过Visual St杨伟中死了udio 2017或更高版别支撑Linux或macOS等渠道以及Windows;

带有AVX2的处理器(即,2013年发布的Haswell微体系结构的Intel处理器和2017年发布的Zen微体系结构的AMD处理器);

最近的C ++编译器(例如,GNU GCC或LLVM CLANG或Visual Studio 2017),咱们假定C ++ 17。GNU GCC 7或更高版别或LLVM的clang 6或更高版别。

此万蛊天帝代码在Apache License 2.0下供给。

在Windows下,咱们运用windows/dirent_portable.h文件(在咱们的库代码之外)构建一些东西

代码示例 #include "simdjson/jsonparser.h" /... const char * filename = ... // //运用您想要的任何办法获取JSON文档的字符串 std::string_view p = get_corpus(filename); ParsedJson pj; pj.allocateCapacity(p.size);//分配内存以解析p.size字节 const int res = json_parse(p, pj); //进行解析,成功时回来0 //解析完结! if(res!= 0){ //您能够运用“simdjson / simdjson.h”标头来拜访过错音讯 std::cout << "Error parsing:" << simdjson::errorMsg(res) << std::endl; } //你能够pescm安全地删去字符串内容 free((void*)p.data); //能够在这里运用ParsedJson文档 // js能够与其他json_parse调用一同运用。

假如您不介意为每个新的JSON文档分配内存开支,也能够运用更简略的API:

#include "simdjson/jsonparser.h" / ... const char * filename = ... // std::string_view p = get_corpus(filename); ParsedJson pj = build_parsed_json(p恋夏38℃); //进行解析 //此刻你不再需求p,能够履行aligned_free((void *)p.data) if( ! pj.isValid ) { //出错了 } 用法:简略的版别

有关用法,请参阅“singleheader”存储库三国群豪传的文件“amalgamation_demo.cpp”。这不需求特定的构建体系:只需在包括途径中仿制项目中的文件即可。然后,您能够十分简略地包括它们:

#include #include "simdjson.h" #include "simdjson.cpp" int main(int argc, char *argv[]) { const char * filename = argv[1]; std::string_view p = get_corpus(filename); ParsedJson pj = build_parsed_json(p); // do the parsing if( ! pj.isValid ) { std::cout << "not valid" << std::endl; } else { std::cout << "valid" << std::endl; } return EXIT_SUCCESS; }

咱们需求AVX2指令的硬件支撑。您有必要保证指示编译器依据需求运用这些阐明。在GNU GCC或LLVM clang等编译器下,-march=native最近的Intel处理器(Haswell或更好)上运用的标志就足够了。为了便于二进制文件的可移植性,您还能够直接指定Haswell处理器(-march=haswell)。您也能够运用标志-mavx2 -mbmi2。在Visual Studio下,您需求定位x64并增加标志/arch:AVX2。

留意:在某些设置中,或许需求预编译simdjson.cpp而不是包括它。

用法(在Linux或macOS等渠道上运用旧版Makefile)

要求:最近的clang或gcc,和make。咱们主张至少运用GNU GCC / G ++ 7或LLVM clang 6.需求像Linux或macOS这样的体系。

测验:

make make test

要运转基准测验:

make parse ./parse jsonexamples/twitter.json

在Linux下,该parse指令供给了功用计数器的详细分小鲤鱼历险记变身口诀析。

运转比较基准测验(与其他解析器):

make benchmark 用法(在Linux或macOS等渠道上运用CMake)

要夫君仅有的名贵求:咱们需求最新版其他cmake。在macOS上,装置cmake的最简略办法或许是运用brew然后键入

brew install cmake

你需求一个像clang或gcc这样的最新编译器。咱们主张至少运用GNU GCC / G ++ 7或LLVM clang 6.14岁小学生例如,您能够运用brew装置最新的编译器:

brew install gcc@8

可选:您需求经过设置CC和CXX变量通知cmake您期望运用哪个编译器。bash下,你能够用比如指令这样做export CC=gcc-7和export CXX=g++-7。

陈周武

构建:在项目存储库中,履行以下操作:

mkdir build cd build cmake .. make make test

默许情况下,它构建一个同享库(例如,Linux上的libsimdjson.so)。

您能够构建一个静态库:

mkdir buildstatic cd buildstatic cmake -DSIMDJSON_BUILD_STATIC=ON .. make make te黄伟汶st

在某些情况下,您或许期望指定编译器,尤其是在体系上的默许编译器太旧的情况下。您能够按以下过程操作:

brew install gcc@8 mkdir build cd build export CXX=g++-8 CC=gcc-8 cmake .. make make test 用法(运用Visual Studio在Windows上进行CMake)

咱们假定您有一台一般的Windows PC,至少包括Visual Studio 2017和支撑AVX2的x64处理器(2013 Intel Haswell或更高版别)。

从GitHub获取simdjson代码,例如,运用克隆它;

装置。装置时,请保证cmake从指令行问询是否可用。请挑选最新版其他cmake;

在simdjson中创立一个子目录,例如VisualStudio;

运用shell,转到这个新创立的目录;

cmake -DCMAKE_GENERATOR_PLATFORM=x64 ..在VisualStudio存储库中键入shell 。(或许,假如要构建DLL,能够运用指令行cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DSIMDJSON_BUILD_STATIC=OFF ..)

最终一个指令在新创立的目录中创立了一个Visual Studio解决方案文件(例如simdjson.sln)。在Visual Studio中翻开此文件。您现在应该能够构建项目并运转测验。例如,在Solution Explorer窗口(可从View菜单中取得)中,右键单击ALL_BUILD并挑选Build。要测验代码,仍然在Solution Explorer窗口中,挑选RUN_TESTS并选胡大宝直播间择Build。

Windows,Linux和MacOS上的用户能够simdjson运用他们喜爱的shell中的一个指令下载和装置。

在Linux和MacOS上:

$ ./vcpkg install simdjs厝,Simdjson:一个超高速的JSON解析东西,蝌蚪on

将构建并装置simdjson为静态库。

在Wi长垣蘧孔学校ndows(64位)上:

.\vcpkg.exe install simdjson:x64-wi厝,Simdjson:一个超高速的JSON解析东西,蝌蚪ndows

将构建并装置simdjson为同享库。

.\vcpkg.exe install simdjson:x64-windows-static

将构建并装置simdjson为静态库。

这些指令还将打印出有关怎么运用MSBuild或依据CMake的项目库的阐明。

假如您发现simdjson顺便的版别vcpkg已过期,请随时经过提交vcpkg问题或创立PR 向社区陈述。

东西

json2json mydoc.json解析文档,结构模型,然后将成果转储回标准输出

json2json -d mydoc.json解析文档,结构模型,然后将模型(作为磁带)转储到标准输出。磁带格局在随附文件中描绘tape.md

minify mydoc.json`缩小JSON文档,将成果输出到标准输出。缩小意味着删去不需求的空格字符。

咱们供给快速解析器。它依据各种规格彻底验证输入。解析器构建一个有用的不可变(只读)DOM(文档 – 方针模型),今后能够拜访它。

为了简化工程,咱们做了一些假定:

咱们支撑U霍洛维茨在莫斯科TF-8(以及ASCII),没有其他(没有拉丁语,没有UTF-16)。咱们不以为这是一个真实的束缚,由于咱们以为没有任何严峻的应用程序需求在没有ASCII或UTF-8编码的情况下处理JSON数据;

JSON文档中学校强奸的一切字符串最多可包括UTF-8(4GB)中的4294967295个字节。要强制履行此束缚,咱们回绝解析包括超越4294967295字节(4GB)的文档。这应该习惯大多数JSON文档;

咱们假定AVX2支撑在AMD和英特尔出产的一切最新干流x86处理器中都可用。虽然能够完结,但不包括对非x86处理器的支撑。咱们方案支撑ARM处理器(恳求协助);

假如发作毛病,咱们只会陈述毛病,而不会指出问题的性质。(这能够在不影响功用的情况下轻松改善);

在标准答应的情况下,咱们答应方针内的重复键(像sajson这样的其他解析器也这样做);

功用针对跨过至少几十千字节到几兆字节的JSON文档进行了优化:有必要解析许多小型JSON文档或一个真实巨大的JSON文档的功用问题是不同的。

咱们的方针不是供给通用的JSON库。像RapidJSON这样的库供给的不仅仅是解析,它还能够协助您生成JSON并供给各种其他便利的功用。咱们只解析文档。

特征

输入字符串未修改,(像sajson和RapidJSON这样的解析器运用输入字符厝,Simdjson:一个超高速的JSON解析东西,蝌蚪串作为缓冲区)。

咱们将整数和浮点数解析为独自的类型,这答应咱们支撑[-922337203厝,Simdjson:一个超高速的JSON解析东西,蝌蚪6854775808,9223372036854775808]中的大型64位整数,如Java long或C / C ++ long long。在区别整数和浮点数的解析器中,并非一切解析器都支撑64位整数。(例如,sajson回绝整数大于或等于2147483648的JSON文件.FreeJSON将解析包括过长整数的文件,如18446744073709551616作为浮点数)当咱们无法将整数表明为带符号的64位时值,咱们回绝JSON文档。

在解析过程中进行完好的UTF-8验证(像fastjson,gason和dropbox json11这样的解析器不会进行UTF-8验证);彻底验证了这些数字(像gason和ultranjson这样的解析器将承受[0e+]为有用的JSON);验证未转义字符的字符串内容(像fastjson和ultrajson这样的解析器承受未转义的换行符和字符串中的标签)。

Architecture

解析器分两个阶段作业:

阶段1.(查找符号)快速标识结构元素,字符串等。咱们在那个阶段验证UTF-8编码。

阶段2.(结构构建)触及构建排序的“树”(详细化为磁带)以阅读数据。在此阶段解析字符串和数字。

以下是将解析后的JSON转储回字符串的代码示例:

ParsedJson::iterator pjh(pj); if (!pjh.isOk) { std::cerr << " Could not iterate parsed result. 梁永涛" << std::endl; return EXIT_FAILURE; } compute_dump(pj); // // where compute_dump is : void compute_dump(ParsedJson::iterator &pjh) { if (pjh.is_object) { std::cout << "{"; if (pjh.down) { pjh.print(std::cout); // must be a string std::cout << ":"; pjh.next; compute_dump(pjh); // let us recurse while (pjh.next) { std::cout << ","; pjh.print(std::cout); std::cout << ":"; pjh.next; compute_dump(pjh); // let us recurse } pjh.up; } std::cout << "}"; } else if (pjh.is_array) { std::cout << "["; if (pjh.down) { compute_dump(pjh); // let us recurse while (pjh.next) { std::cout << ","; compute_dump(pjh); // let us recurse } pjh.up; } std::cout << "]"; } else { pjh.print(std::cout); // just print the lone value } } 张境原坐月子

以下函数将查找一切user.id整数:

void simdjson_traverse(std::vector &answer, ParsedJson::iterator &i) { switch (i.get_type) { case '{': if (i.down) { do { bool founduser = equals(i.get_string, "user"); i.next; // move to value if (i.is_object) { if (founduser && i.move_to_key("id")) { if (i.is_integer) { answer.push_back(i.get_integer); } i.up; } simdjson_traverse(answer, i); } else if (i.is_array) { simdjson_traverse(answer, i); } } while (i.next); i.up; } break; case '[': if (i.down) { do { if (i.is_object_or_array) { simdjson_traverse(answer, i); } } while (i.next); i.up; } break; case 'l': case 'd': case 'n': case 't': case 'f': default: break; } } 深化比较

假如您想了解各种解析器怎么验证给定的JSON文件:

make allparserscheckfile ./allparserscheckfile myfile.json

关于功用比较:

make parsingcompetition ./parsingcompetition myfile.json

进行更广泛的比较:

make allparsingcompetition ./allparsingcompetition myfile.js郭洪伟on

*参阅来历github,由周大涛编译,转载请注明来自FreeBuf.COM

CES AMD Mac
声明:该文观厝,Simdjson:一个超高速的JSON解析东西,蝌蚪点仅代表作者自己,搜狐号系信息发布渠道,搜狐仅供给信息存储空间效劳。