当前位置:首页 > 奇闻趣事

json解析 每秒解析千兆字节的 JSON 解析器开源了

本文转自我们网站InfoQ,译者不详。除了推荐simdjson,我还想测试一下微信平台编辑器的代码风格功能。

事实证明,微信文章的代码展示能力很强。非常好。

最近GitHub打开了一个JSON解析器simdjson。对比其他常用的解析器,结果表明simdjson的解析速度达到了2.2GB/s,远远快于其他解析器。下面,我们将详细介绍simdjson。以下全文是GitHub上simdjson的文档。

JSON文档在互联网上无处不在,服务器花大量时间解析这些文档。我们希望在充分验证(包括字符编码)的同时,尽可能使用通用的SIMD指令来加快JSON的解析速度。

一些性能结果

与最先进的解析器(比如RapidJSON)相比,我们可能用了四分之一甚至更少的指令,而sajson只有一半。据我们所知,simdjson是第一个在商用处理器上以每秒千兆位运行的完全验证过的json解析器。

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

基本要求

通过 Visual Studio 2017 或更高版本支持 Linux、macOS 以及 Windows 等平台;带有 AVX2 的处理器;支持最近的 C++ 编译器(例如,GNU GCC 或 LLVM CLANG 或 Visual Studio 2017),我们假设是 C++ 17,GNU GCC 7 或更高版本,或者 LLVM 的 clang 6 或更高版本;提供一些基准测试脚本,可以是 bash 和其他常用的实用命令程序,但是是可选的。 许可

代码由Apache许可证2.0授权。

在Windows下,我们使用windows/dirty _ portable.h文件(在我们的库代码之外)来构建一些工具:基于自由的MIT许可证。

代码示例

#include"simdjson/jsonparser.h"/...constchar* filename = ... //// use whatever means you want to get a string of your JSON document std::string_view p = get_corpus(filename); ParsedJson pj; pj.allocateCapacity(p.size()); // allocate memory for parsing up to p.size() bytes boolis_ok = json_parse(p, pj); // do the parsing, return false on error // parsing is done! // You can safely delete the string content free((void*)p.data()); // the ParsedJson document can be used here // js can be reused with other json_parse calls.

如果您不介意为每个新的JSON文档分配内存,您也可以使用一个更简单的应用编程接口:

#包括" simdjson/jsonparser.h"/...constchar* filename =...//STD::string _ view p = get _文集(文件名);ParsedJson pj = build _ parsed _ JSON(p);//做解析//此时你不再需要p,可以做aligned _ free((void *)p . data())if(!pj.isValid() ) {//出问题了}

使用

简单头文件

查看头文件代码库的“singleheader”,查看文件“amalgamation _ demo.cpp”了解用法。不需要使用特定的构建系统:只需将文件复制到项目中的路径。然后,您可以包含它们:

#include<iostream> #include"simdjson.h" #include"simdjson.cpp" intmain(intargc, char*argv[]){ constchar* 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; } returnEXIT_SUCCESS; }

注意:在某些环境中,可能需要预编译simdjson.cpp,而不是包含它。

在Linux或macOS上使用旧的Makefile

要求:最新的金属(或gcc)和制造。至少推荐GNU GCC/G ++ 7或者LLVM clang 6,Linux或者macOS系统。

测试:

make maketest

运行基准测试:

makeparse ./parse jsonexamples/twitter.json

在Linux上,parse命令提供了对性能计数器的详细分析。

运行其他基准测试进行比较(使用其他解析器):

makebenchmark

在Linux或macOS等平台上使用CMake

要求:需要最新版本的cmake。在macOS上,安装cmake最简单的方法可能是使用brew。

brewinstall cmake

你需要一个新的编译器,比如clang或者gcc。至少推荐GNU GCC/G ++ 7或者LLVM clang 6。例如,您可以使用brew安装最新的编译器:

brewinstallgcc@8

可选:你需要通过设置CC和CXX变量来告诉cmake你要用哪个编译器。在bash中,可以使用export CC = gcc-7、export CXX = g+ 7等命令。

构建:在项目代码库中执行以下命令:

mkdirbuild cdbuild cmake.. make maketest

CMake会建一个库。默认情况下,它会构建一个共享库(例如Linux上的libsimdjson.so)。

您可以构建一个静态库:

mkdirbuildstatic cdbuildstatic cmake-DSIMDJSON_BUILD_STATIC=ON .. make maketest

在某些情况下,您可能希望指定一个编译器,尤其是当系统默认编译器太旧时。您可以按照以下步骤操作:

brewinstall gcc@8 mkdirbuild cdbuild exportCXX=g++-8 CC=gcc-8 cmake.. make maketest

通过Visual Studio在Windows上使用CMake

我们假设你有一台至少安装了Visual Studio 2017的普通Windows PC,支持AVX2 (2013 Haswell或更高版本)的x64处理器。

从 GitHub 获取 simdjson 代码,例如,使用 GitHub Desktop 克隆它。安装 CMake。在安装时,请确保可以从命令行使用 cmake。请选择最新版本的 cmake。在 simdjson 中创建一个子目录,例如 VisualStudio。在 shell 中转到这个新创建的目录。在 shell 中键入 cmake -DCMAKE_GENERATOR_PLATFORM=x64 …(或者,如果要构建 DLL,可以使用命令行 cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DSIMDJSON_BUILD_STATIC=OFF …)。最后一个命令在新创建的目录(例如 simdjson.sln)中创建了一个 Visual Studio 解决方案文件。在 Visual Studio 中打开这个文件。你现在应该能够构建项目并运行测试。例如,在“Solution Explorer”窗口中,右键单击“ALL_BUILD”,并选择“Build”。要测试代码,仍然在 Solution Explorer 窗口中,选择 RUN_TESTS,再选择 Build。 工具 json2json mydoc.json 解析文档,构造模型,然后将结果输出到标准输出。json2json -d mydoc.json 解析文档,构造模型,然后将模型输出到标准输出。格式在随附的文件 tape.md 中有描述。minify mydoc.json 缩小 JSON 文档,将结果输出到标准输出。缩小意味着删除不必要的空格。 范围

我们提供了一个非常快速的解析器。它完全按照各种规范验证输入。解析器将建立一个不可变的(只读的)文档对象模型供后续访问。

为了简化项目,我们做了一些假设。

支持 UTF-8(以及 ASCII),没有别的(没有 Latin,没有 UTF-16)。我们不认为这是一个真正的限制,因为我们不认为会有哪个严肃的应用程序需要在没有 ASCII 或 UTF-8 编码的情况下处理 JSON 数据。我们将字符串存储为以 NULL 作为终止符的 C 字符串。因此,我们假设字符串中不包含 NULL 字符。我们假设支持 AVX2,这在 AMD 和英特尔生产的所有最新主流 x86 处理器中都可用。不支持非 x86 处理器,尽管我们可以支持。我们计划支持 ARM 处理器。如果发生故障,我们只会报告故障,而不会指出问题的性质。在规范允许的情况下,我们允许对象内存在重复的 key。性能针对跨越几千字节到几兆字节的 JSON 文档进行了优化:解析很多小型 JSON 文档和一个大 JSON 文档的性能问题是不一样的。

我们的目标不是提供一个通用的JSON库。像RapidJSON这样的库不仅提供解析功能,还可以用来生成JSON,提供各种其他方便的功能。我们只解析文档。

特点

不需改输入的字符串。(像 sajson 和 RapidJSON 这样的解析器使用输入字符串作为缓冲区。)将整数和浮点数解析为单独的类型,这样可以支持 [-9223372036854775808,9223372036854775808] 区间的 64 位整数,就像 Java 的 long 或 C/C++ 的 long long。在区分整数和浮点数的解析器中,并非所有解析器都支持 64 位整数。(例如,sajson 不支持包含大于或等于 2147483648 整数的 JSON 文件。FreeJSON 将长整数解析为浮点数。)当我们无法将整数表示为带符号的 64 位值时,我们就拒绝解析 JSON 文档。在解析过程中进行完整的 UTF-8 验证。(像 fastjson、gason 和 dropbox json11 这样的解析器不会进行 UTF-8 验证。)完全验证数字。(像 gason 和 ultranjson 这样的解析器会接受 [0e+] 这样的数字。)验证字符串内容中的未转义字符。(像 fastjson 和 ultrajson 这样的解析器接受字符串中未转义的换行符和制表符。) 架构

解析器有三个阶段:

阶段 1,(查找标记)快速标识结构元素、字符串等。我们在这个阶段验证 UTF-8 编码。阶段 2,(结构构建)构建排序的“树”(物化为磁带),以方便访问数据。我们在这个阶段解析字符串和数字。 访问已解析的文档

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

ParsedJson::iterator pjh(pj); if(!pjh.isOk()) { std::cerr<< " Could not iterate parsed result. "<< std::endl; returnEXIT_FAILURE; } compute_dump(pj); // // where compute_dump is :

void compute _ dump(ParseDjson::iterator & amp;pjh){ if(pjh . is _ object()){ STD::cout & lt;& lt"{";if(pjh . down()){ pjh . print(STD::cout);//必须是string SD::cout & lt;& lt":";pjh . next();compute _ dump(pjh);//让我们递归(pjh . next()){ STD::cout & lt;& lt",";pjh . print(STD::cout);STD::cout & lt;& lt":";pjh . next();compute _ dump(pjh);//让我们递归} pjh . up();} STD::cout & lt;& lt"}";} else if(pjh . is _ array()){ STD::cout & lt;& lt"[";if(pjh . down()){ compute _ dump(pjh);//让我们递归(pjh . next()){ STD::cout & lt;& lt",";compute _ dump(pjh);//让我们递归} pjh . up();} STD::cout & lt;& lt"]";} else { pjh . print(STD::cout);//只打印唯一的值}}

以下函数将查找所有user.id整数:

voidsimdjson_traverse(std::vector<int64_t> &answer, ParsedJson::iterator &i){switch(i.get_type()) {case'{':if(i.down()) {do{boolfounduser = equals(i.get_string(), "user");i.next(); // move to valueif(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);} elseif(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文件:

makeallparserscheckfile./allparserscheckfile myfile.json

性能比较:

makeparsingcompetition./parsingcompetitionmyfile.json

更广泛的比较:

makeallparsingcompetition./allparsingcompetitionmyfile.json

原文英文:https://github.com/lemire/simdjson

1.《json解析 每秒解析千兆字节的 JSON 解析器开源了》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《json解析 每秒解析千兆字节的 JSON 解析器开源了》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/guonei/798492.html

上一篇

血溅鸳鸯楼 血溅鸳鸯楼时,为何武松连端茶送水的丫鬟也不放过?原因很简单

下一篇

人参果 这么多年,一直错怪了人参果......

保护色设置 如何在阅读PDF文档,设置专属你的保护色

保护色设置 如何在阅读PDF文档,设置专属你的保护色

是否有必要长时间使用电脑阅读PDF文档,但当人们长时间阅读电脑文档时,会感到不舒服、干燥和眼花缭乱。 事实上,我们可以设置文档的背景颜色来缓解眼睛的不适。 一般情况下,我们会选择绿色豆瓣酱,而不是白色背景。 但是,有时候豆沙绿并不能保护我们的视力。绿色背景和白色背景...

如何将图片转换成word文档 怎么把图片的文字转换成word文本

  • 如何将图片转换成word文档 怎么把图片的文字转换成word文本
  • 如何将图片转换成word文档 怎么把图片的文字转换成word文本
  • 如何将图片转换成word文档 怎么把图片的文字转换成word文本

pdf怎样转换成word文档 怎么快速把pdf文件转换成word文档?

  • pdf怎样转换成word文档 怎么快速把pdf文件转换成word文档?
  • pdf怎样转换成word文档 怎么快速把pdf文件转换成word文档?
  • pdf怎样转换成word文档 怎么快速把pdf文件转换成word文档?

pdf转化为word软件 怎么快速把pdf文件转换成word文档?

  • pdf转化为word软件 怎么快速把pdf文件转换成word文档?
  • pdf转化为word软件 怎么快速把pdf文件转换成word文档?
  • pdf转化为word软件 怎么快速把pdf文件转换成word文档?

云文档 试过市面上这几家云文档后 我最终选择了金山文档

  • 云文档 试过市面上这几家云文档后 我最终选择了金山文档
  • 云文档 试过市面上这几家云文档后 我最终选择了金山文档
  • 云文档 试过市面上这几家云文档后 我最终选择了金山文档

金山文档网页版 腾讯文档真心比不上金山文档的N大理由

上班一直是人类最痛苦的生活之一,工作更痛苦。 每天坐在工作站上面对Excel,word,PPT,真是头大到崩溃。 这不是最痛苦的,最致命的是反复修改。桌面上有一百多个版本。删除的时候不知道从哪里开始。为了应对可怕的改版过程,我不得不找有没有办公软件的“宝典绝学”。...

文档在线 在线文档发烧友告诉你,哪个才是在线办公的神器

  • 文档在线 在线文档发烧友告诉你,哪个才是在线办公的神器
  • 文档在线 在线文档发烧友告诉你,哪个才是在线办公的神器
  • 文档在线 在线文档发烧友告诉你,哪个才是在线办公的神器
xctf 经典整数溢出漏洞示例 XCTF int_overflow

xctf 经典整数溢出漏洞示例 XCTF int_overflow

无符号短整型的两个变量var1和var2假设为var1 = 1,var2 = 65537。  也就是说,在复制字符串的过程中,输入0x14个字符后,可以覆盖函数返回地址,具体是不是0x14个字符。我们再来看看汇编语言。  在复制字符串之前,请将复制的源地址和目的地址...