当前位置: 首页 > news >正文

simdjson 高性能JSON解析C++库

simdjson 是什么

simdjson 是一个用来解析JSON数据的 C++ 库,它使用常用的 SIMD 指令和微并行算法来每秒解析千兆字节的 JSON,在Velox, ClickHouse, Doris 中均有使用。

加载和解析 JSON documents

出于性能考虑,simdjson 需要一个末尾有几个字节(simdjson::SIMDJSON_PADDING)的字符串,这些字节可以被读取,但它们的内容不会影响解析。实际上,这意味着 JSON 输入应存储在末尾带有 simdjson::SIMDJSON_PADDING 额外字节的内存区域中。用户不需要对这些额外的字节指定值。

simdjson 库提供了一个类似树的 API,可以通过创建 ondemand::parser 并调用 iterate() 方法来访问它。 iterate() 方法可以快速索引输入字符串,并且可以检测到一些错误(JSON不合法)。以下是针对不同字符串表达方式的示例:

ondemand::parser parser;
auto json = padded_string::load("twitter.json"); // load JSON file 'twitter.json'.
ondemand::document doc = parser.iterate(json); // position a pointer at the beginning of the JSON data
ondemand::parser parser;
auto json = "[1,2,3]"_padded; // The _padded suffix creates a simdjson::padded_string instance
ondemand::document doc = parser.iterate(json); // parse a string
ondemand::parser parser;
char json[3+SIMDJSON_PADDING];
strcpy(json, "[1]");
ondemand::document doc = parser.iterate(json, strlen(json), sizeof(json));
std::string data = "my data";
simdjson::padded_string my_padded_data(data); // copies to a padded buffer

建议不要在应用程序中创建许多 std::string 或许多 std::padding_string 实例来存储 JSON 数据,而是重用相同的缓冲区并限制内存分配。

Documents 就是迭代器

simdjson 解析JSON是按需的,document 并不是被完全解析后的JSON,他是一个用于迭代JSON文本的迭代器。当你在迭代时会触发解析原始的JSON文本,处理括号、逗号之类的分隔符,保证你能够得到结果。这么做对于性能提升非常关键,可以跳过不需要的解析动作

Parser, document 和 JSON的作用域

为了代码合法,需要在解析JSON时保证(1)parser 实例(2)输入的JSON string(3)document实例 都存活。并且要遵守以下两点:

  1. 一个 parser 实例同时最多有一个 document,因为它持有用于解析而分配的内存。
  2. 按照设计,每个JSON文档应该只有一个 document 实例。因此,如果必须将文档实例按引用传递给函数以避免复制,避免按值传递。

在 iterate 调用期间,原始 JSON 文本永远不会被修改——只能读取。用完 document 后,可以安全地丢弃数据源(无论是文件还是字符串)。

为了获得最佳性能,Parser实例应该在多个文件上重用:否则会不必要地重新分配内存,这是一个开销较大的过程。

如果需要同时解析多个 document,则应该有多个parser实例。

string_view

simdjson使用std::string_view表示已解析的字符串。string_view避免了复制数据的需要和以空字符结尾的C字符串的陷阱。它使用户更容易将数据复制到他们自己喜欢的类实例中。std::string_view 实例实际上只是指向内存中表示字符串的区域的指针。在 simdjson 中,我们返回 std::string_view 实例,这些实例要么指向您解析的输入字符串内或parser实例内的临时字符串缓冲区,该缓冲区在parser实例被销毁或使用它来解析另一个document之前一直有效。

使用解析后的 JSON

需要牢记以下规则:

  1. 当访问 document 时,document 实例应保留在作用域内:它是“迭代器”,用于跟踪您在 JSON 文档中的位置。根据设计,每个 JSON 文档有且仅有一个document实例。
  2. 因为 document 实际上只是一个迭代器,所以在访问同级对象或数组之前,您必须完全消耗当前对象或数组。
  3. 值只能使用一次,如果打算多次需要它们,应该获取并存储它们。应该只访问对象的键一次。应该只检查一次数组的值

以下具体说明指示如何在启用异常时使用 JSON:

  • 校验使用的东西。调用iterate时,document 会被快速索引。如果它不是有效的Unicode(UTF-8)字符串,或者如果存在未关闭的字符串,则可能会立即报告错误。但是它没有完全验证整个JSON。仅完全验证被使用的值和相关结构。这意味着在遍历document的每一步,都可能遇到错误。可以处理带有异常或错误代码的错误。

  • 提取值。可以将 JSON元素转换为 native type:double(element)。这适用于std::string_view, double, uint64_t, int64_t, bool, ondemand::object and ondemand::array. 也有显示方法 get_string(), get_double(), get_uint64(), get_int64(), get_bool(), get_object() and get_array(). 当调用显式或隐式的转换方法后,可能会抛出无法转换的异常。

  • 字段访问。要获取对象中“foo”字段的值,请使用 object["foo"]。这将扫描对象,查找具有匹配字符串的字段,并进行逐个字符的比较。如果对象中没有这样的键,可能会生成错误 simdjson::NO_SUCH_FIELD,可能会抛出异常。为了获得最佳性能,应该尝试按照键在文档中出现的顺序来查询键。

  • 输出成string。给定 JSON 文档中的文档、值、数组或对象,您可以输出适合再次解析为 JSON 内容的 JSON 字符串版本: simdjson::to_json_string(element).对 to_json_string 的调用会完全consume该元素:如果将其应用于 document,则 JSON 指针将前进到document的末尾。to_json_string 函数不应与获取字符串实例的值相混淆,该字符串实例是使用指向parser实例内的内部字符串缓冲区的轻量级 std::string_view 实例进行转义和表示的。为了说明这一点,以下两个代码段中的第一个将打印带有引号的未转义字符串“test”,而第二个代码段将打印字符串的转义内容(不带引号):test。

    // serialize a JSON to an escaped std::string instance so that it can be parsed again as JSON
    auto silly_json = R"( { "test": "result"  }  )"_padded;
    ondemand::document doc = parser.iterate(silly_json);
    std::cout << simdjson::to_json_string(doc["test"]) << std::endl; // Requires simdjson 1.0 or better
    
    // retrieves an unescaped string value as a string_view instance
    auto silly_json = R"( { "test": "result"  }  )"_padded;
    ondemand::document doc = parser.iterate(silly_json);
    std::cout << std::string_view(doc["test"]) << std::endl;
    
  • 还有一些其他的,详见官方文档

错误处理

默认情况下,simdjson 库会在出现错误时引发异常 (simdjson_error)。如果在代码中省略了 try-catch,未捕获的异常将停止程序,有两种方法处理错误,一是单个 try/catch 子句进行错误处理,二是使用无异常方法。

  1. try/catch 子句进行错误处理

     bool simple_error_example_except() {TEST_START();ondemand::parser parser;auto json = R"({"bad number":3.14.1 })"_padded;try {ondemand::document doc = parser.iterate(json);double x = doc["bad number"].get_double();std::cout << "Got " << x << std::endl;return true;} catch(simdjson_error& e) {// e.error() == NUMBER_ERRORstd::cout << e.error() << std::endl;return false;}}
    
  2. 使用异常和单个 try/catch 子句进行错误处理使代码变得简单,但它使您无法控制错误。为了更轻松地调试或更强大的错误处理,您可能需要考虑使用无异常方法。整个 simdjson API 都可以使用无异常方法。所有可能失败的 simdjson API 都会返回 simdjson_result,它是一个 <value, error_code> 对。可以使用 .get() 检索值而不生成异常,如下所示:

    ondemand::document doc;
    auto error = parser.iterate(json).get(doc);
    if (error) { cerr << error << endl; exit(1); }
    

    如果没有错误,则返回错误代码 simdjson::SUCCESS:它的计算结果为布尔值 false。有几个错误代码来指示错误,它们的计算结果为布尔值为 true。当使用无异常的API时,有责任在使用结果之前检查错误:如果有错误,结果值将无效,使用它将导致未定义的行为。

    用一个例子来说明,我们尝试访问一个无效的值(3.14.1)。如果我们想继续而不抛出和捕获异常,我们可以这样做:

    bool simple_error_example() {ondemand::parser parser;auto json = R"({"bad number":3.14.1 })"_padded;ondemand::document doc;if (parser.iterate(json).get(doc) != SUCCESS) { return false; }double x;auto error = doc["bad number"].get_double().get(x);// returns "simdjson::NUMBER_ERROR"if (error != SUCCESS) {std::cout << error << std::endl;return false;}std::cout << "Got " << x << std::endl;return true;
    }
    

    参考

    https://github.com/simdjson/simdjson/blob/master/doc/basics.md

    https://simdjson.org/

相关文章:

simdjson 高性能JSON解析C++库

simdjson 是什么 simdjson 是一个用来解析JSON数据的 C 库&#xff0c;它使用常用的 SIMD 指令和微并行算法来每秒解析千兆字节的 JSON&#xff0c;在Velox, ClickHouse, Doris 中均有使用。 加载和解析 JSON documents 出于性能考虑&#xff0c;simdjson 需要一个末尾有几个…...

安卓Context上下文

目录 前言一、Context简介二、Application Context2.1 Application Context的创建过程2.2 Application Context的获取过程 三、Activity的Context创建过程四、Service的Context创建过程 前言 Context也就是上下文对象&#xff0c;是Android较为常用的类&#xff0c;但是对于Co…...

实验13 简单拓扑BGP配置

实验13 简单拓扑BGP配置 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤 一、 原理描述 BGP&#xff08;Border Gateway Protocol&#xff0c;边界网关协议&#xff09;是一种用于自治系统间的动态路由协议&#xff0c;用于在自治系统&#xff08;AS&…...

面试题分享--Spring02

Spring 框架中都用到了哪些设计模式?(必会) 1. 工厂模式&#xff1a;BeanFactory 就是简单工厂模式的体现&#xff0c;用来创建对象的实例 2. 单例模式&#xff1a;Bean 默认为单例模式 3. 代理模式&#xff1a;Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成…...

基于QT和C++实现的中国象棋

一&#xff0c;源码 board.h #ifndef BOARD_H #define BOARD_H#include <QWidget> #include "Stone.h"class Board : public QWidget {Q_OBJECT public:explicit Board(QWidget *parent 0);bool _bRedTurn; // 红方先走int _currentPlayer; // 当前玩家&…...

Mojo崛起:AI-first 的编程语言能否成为新流行?

眨眼之间&#xff0c;你可能会错过又一种编程语言的发明。 有个笑话说&#xff0c;程序员花费20%的时间编写代码&#xff0c;80%的时间决定使用什么语言。 事实上&#xff0c;编程语言如此之多&#xff0c;以至于我们不确定实际有多少种。据估计&#xff0c;至少有700种编程语…...

【数据结构与算法】哈夫曼树与哈夫曼编码

文章目录 哈夫曼树&#xff08;最优二叉树&#xff09;定义举个&#x1f330;&#xff08;WPL的计算&#xff09; 哈夫曼树的构造&#xff08;最优二叉树的构造&#xff09;举个&#x1f330; 哈夫曼树的性质 哈夫曼编码定义构造 哈夫曼树&#xff08;最优二叉树&#xff09; …...

基于多头注意力机制卷积神经网络结合双向门控单元CNN-BIGRU-Mutilhead-Attention实现柴油机故障诊断附matlab代码

在使用这些深度学习库时&#xff0c;你可以按照以下步骤构建CNN-BIGRU-Multihead-Attention模型&#xff1a; 导入所需的库和模块。例如&#xff0c;在使用TensorFlow时&#xff0c;你可以导入tensorflow库和其他需要的模块。 定义输入层。根据你的数据&#xff0c;定义适当的…...

k8s redis 单节点部署

k8s redis 单节点部署kubectl 执行脚本 kubectl --kubeconfig ~/.kube-rz-real/config apply -f redis-leader.yaml -n rz-dt vi redis-leader.yamlapiVersion: apps/v1 kind: Deployment metadata:name: redis-leader-deploylabels:app: redisrole: leadertier: backend sp…...

科普童话投稿

《科普童话》杂志是由国家新闻出版总署批准、黑龙江省教育厅主管、黑龙江省语言文字报刊社主办的正规期刊。《科普童话》以培养科学素养与创新探索精神为办刊宗旨&#xff0c;以科学与艺术统一为编辑方针&#xff0c;以科学教育、教育科学作为自己的出发点&#xff0c;致力于对…...

【Ardiuno】使用ESP32单片机创建web服务通过网页控制小灯开关的实验(图文)

经过实验测试ESP32单片机的网络连接还是很方便的&#xff0c;这里小飞鱼按照程序实例的代码亲自实验一下使用Esp32生成的网页服务来实现远程无线控制小灯开关功能&#xff0c;这样真的是离物联网开发越来越近了&#xff0c;哈哈&#xff01; 连接好开发板和电路&#xff0c;将…...

百元蓝牙耳机哪款音质最好?四款实力超群机型推荐

在蓝牙耳机市场竞争日益激烈的今天&#xff0c;百元级别的耳机已经具备了令人瞩目的音质表现&#xff0c;对于追求高性价比的消费者来说&#xff0c;如何在众多选项中挑选出一款音质卓越的蓝牙耳机&#xff0c;无疑是一项重要而又充满挑战的任务&#xff0c;今天我将为大家推荐…...

Linux系统之mtr命令的基本使用

Linux系统之mtr命令的基本使用 一、mtr命令介绍二、mtr命令使用帮助2.1 mtr命令的帮助信息2.2 mtr帮助信息解释 三、安装mtr工具四、mtr命令的基本使用4.1 直接使用4.2 设定ping次数4.3 禁用DNS解析4.4 显示IP地址4.5 调整间隔 五、总结 一、mtr命令介绍 mtr命令是一个网络诊断…...

实战tcpdump4.99.4交叉编译

主要是记录交叉编译的一个坑&#xff0c;不知道为什么网上的教程都没遇到过。 环境 libpcap 1.10.4tcpdump 4.99.4WSL 编译步骤 注意事项 注意解压的时候文件夹名需要是libpcap-1.10.4&#xff0c;由于我是在github直接下载zip的压缩包名是libpcap-libpcap-1.10.4.tar.gz解…...

重生奇迹MU召唤术师简介

出生地&#xff1a;幻术园 性 别&#xff1a;女 擅 长&#xff1a;召唤幻兽、辅助魔法&攻击魔法 转 职&#xff1a;召唤巫师&#xff08;3转&#xff09; 介 绍&#xff1a;从古代开始流传下来的高贵的血缘&#xff0c;为了种族纯正血缘的延续及特殊使用咒术的天赋&…...

神经网络模型---AlexNet

一、AlexNet 1.导入tensorflow库&#xff0c;这里给简称为tf库 import tensorflow as tf from tensorflow.keras import datasets, layers, modelsdatasets&#xff1a;是用于训练和测试机器学习模型的数据集合 layers&#xff1a;是构建神经网络模型的关键组成部分 models&a…...

corona渲染器与vray比哪个好?支持云渲染平台吗

​在视觉渲染技术领域&#xff0c;V-Ray和Corona都以其卓越的性能和广泛应用赢得了高度评价。这两款渲染器各有其独特的优势&#xff0c;使得在它们之间做出选择并非易事。不同的应用场景和用户需求可能会让它们各自展现出不同的优势。 一、corona渲染器跟vray怎么样 在比较V-…...

每日一练:攻防世界:Ditf

这是难度1的题吗&#xff1f;&#xff1f;&#xff1f; 拿到一个png图片&#xff0c;第一反应就是CRC爆破&#xff0c;结果还真的是高度被修改了 这里拿到一个字符串&#xff0c;提交flag结果发现不是&#xff0c;那么只可能是密钥之类的了 看看有没有压缩包&#xff0c;搜索…...

约瑟夫环递归算法详解与实现

一、引言 约瑟夫环问题是一个著名的理论问题&#xff0c;其背景是在古罗马时期&#xff0c;有n个犯人被围成一个圈&#xff0c;从第一个人开始报数&#xff0c;每次报到m的人将被处决&#xff0c;然后从下一个人开始重新报数&#xff0c;直到所有人都被处决。这个问题可以用递…...

互联网应用主流框架整合之构建REST风格的系统

REST&#xff08;Representational State Transfer&#xff09;&#xff0c;中文译为“表述性状态转移”&#xff0c;是由Roy Fielding博士在他的博士论文中提出的一种软件架构风格&#xff0c;特别适用于网络应用的设计。REST不是一个标准&#xff0c;而是一种设计原则和约束集…...

vue3-自定义指令来实现input框输入限制

文章目录 前言具体实现分析主要部分详细解析导入和类型定义mounted 钩子函数unmounted 钩子函数指令注册使用 总结 前言 使用vue中的自定义指令来实现input框输入限制 其中关键代码强制触发input &#xff0c;来避免&#xff0c;输入规则外的字符时&#xff0c;没触发vue的响…...

MySQL日志——redolog

redo log&#xff08;重做日志&#xff09; 为什么需要redo log&#xff1f; 在mysql提交一个事务后&#xff0c;这个事务所作的数据修改并不会直接保存到磁盘文件中&#xff0c;而是先保存在buffer pool缓冲区中&#xff0c;在需要读取数据时&#xff0c;先从缓冲区中找&…...

Python热涨落流体力学求解算法和英伟达人工智能核评估模型

&#x1f3af;要点 &#x1f3af;平流扩散简单离散微分算子 | &#x1f3af;相场模拟&#xff1a;简单旋节线分解、枝晶凝固的 | &#x1f3af;求解二维波动方程&#xff0c;离散化时间导数 &#x1f3af;英伟达 A100 人工智能核性能评估模型 | &#x1f3af;热涨落流体动力学…...

【C语言】数组参数和指针参数详解

在写代码的时候难免要把【数组】或者【指针】传给函数&#xff0c;那函数的参数该如何设计呢&#xff1f; 1 一维数组传参 #include <stdio.h> void test(int arr[])//ok? {} void test(int arr[10])//ok? {} void test(int* arr)//ok? {} void test2(int* arr[20])…...

Tuple 元组

文章目录 一、什么是元组 &#xff1f;二、元组的具体操作2.1 创建元组2.1.1 tuple() 创建元组函数和 list() 创建列表函数总结 2.2 元组的元素访问操作2.3 元组的元素计数操作2.4 zip 对象 一、什么是元组 &#xff1f; 列表属于可变序列,可以任意修改列表中的元素。 元组的…...

(资料收藏)王阳明传《知行合一》共74讲,王阳明知行合一音频讲解资料

今天给大家带来的不是软件&#xff0c;而是一份精神食粮——《知行合一》的教程福利。这可不是一般的教程&#xff0c;它关乎心灵&#xff0c;关乎智慧&#xff0c;关乎我们如何在纷繁复杂的世界中找到自己的位置。 咱们得聊聊王阳明&#xff0c;这位明代的大儒&#xff0c;他…...

空气质量预报模式系统WRF-CMAQ

空气污染问题日益受到各级政府以及社会公众的高度重视&#xff0c;从实时的数据监测公布到空气质量数值预报及预报产品的发布&#xff0c;我国在空气质量监测和预报方面取得了一定进展。随着计算机技术的高速发展、空气污染监测手段的提高和人们对大气物理化学过程认识的深入&a…...

Collections.sort()方法总结

Collections.sort()方法总结 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨 Java 中的 Collections.sort() 方法。这个方法是 Java 集合框架中的…...

Java23种设计模式(二)

1、单例模式 单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有…...

Web前端收入来源:探索多元化的盈利渠道

Web前端收入来源&#xff1a;探索多元化的盈利渠道 在数字化时代&#xff0c;Web前端技术日益成为推动互联网业务发展的重要力量。对于前端开发者而言&#xff0c;除了传统的薪资收入外&#xff0c;还存在多种潜在的收入来源。本文将从四个方面、五个方面、六个方面和七个方面…...

手机网站制作公司报价单/做网站优化哪家公司好

荔枝微服务化进程较早&#xff0c;目前已有上千个服务模块&#xff0c;先前的运维平台渐渐无法满足微服务架构下运维管理的需求&#xff0c;于是决定从2018年开始重构运维平台&#xff0c;结合容器化技术&#xff0c;让开发人员尽可能无感知迁移的同时享受容器化带来的诸多好处…...

做网站可以用中文域名备案嘛/推广资源整合平台

目录 eLCDIF接口 相关寄存器 配置步骤 LCD像素时钟的设置 eLCDIF接口 LCDIF是I.MX6U自带的液晶屏幕接口,用于连接RGB LCD接口的屏幕,eLCDIF接口特性如下: 1.支持RGB LCD的DE模式。 2.支持VSYNC模式以实现高速数据传输。 3.支持ITU-R BT.656格式的4:2:2的YCbCr 数字视频…...

怎么做网站原型/百度识图扫一扫

字符串广泛应用在Java编程中&#xff0c;在Java中字符串属于对象&#xff0c;String 类提供了许多用来处理字符串的方法&#xff0c;例如&#xff0c;获取字符串长度、对字符串进行截取、将字符串转换为大写或小写、字符串分割等。 String 类的常用方法&#xff1a; 注意事项&a…...

如皋网站开发/网站一般需要怎么推广

方法一&#xff1a; 开发者选项里面把 Pointer location打开后&#xff0c;就可以直接在ui界面的上方看到坐标值。 方法二&#xff1a; 通过使用adb shell getevent&#xff0c;可以得到如下设备操作后的指令&#xff0c;具体表示的含义&#xff0c;可以参考网上很多的文章&…...

wordpress google ajax/淘宝关键词top排行榜

1、项目目的&#xff1a; 本项目主要通过编写贪吃蛇游戏来学习&#xff0c;熟悉Qt中封装的类。 2、编译环境 VS2019Qt5.9 3、功能实现 主要实现下面所列基本功能&#xff1a; 控制贪吃蛇吃食物 表示蛇控制贪吃蛇上下左右移动控制食物的随机分配控制蛇的增长 暂停游戏结束…...

pa66用途障车做网站/最新国内你新闻

我是python开发, 现在学C, 文中代码格式偏向于python风格, 但不影响代码使用, 文中的代码已通过编译且正常运行: 文章目录一. 指针1.1 注意事项:2.1 难点理解一. 指针 1.1 注意事项: 1.1.1 在printf输出函数中, 输出内存地址的格式控制符是%p, 地址采用十六进制的格式显示.1.…...