写点什么

高性能 Rust JSON 库 sonic-rs 优化实践

  • 2024-03-26
    北京
  • 本文字数:2008 字

    阅读完需:约 7 分钟

大小:904.33K时长:05:08
高性能 Rust JSON 库 sonic-rs优化实践

一、sonic-rs 介绍

sonic-rs 是一个基于 SIMD 的高性能 Rust JSON 库,是 sonic JSON 库的 Rust 版本。


字节跳动 sonic 开源项目如今包含了不同语言的多个 JSON 库(如下)。其中,sonic-go 最先开源,使用了 JIT 和 SIMD 技术,sonic-cpp 使用了 C++ 模板和 SIMD 技术,这两个 JSON 库均已经在字节内部得到了较大规模的落地。在成本优化大背景下,为了帮助 Golang 业务迁移 Rust,优化 Rust JSON 性能,我们基于 JSON 方面的优化经验和实践,用纯 Rust 语言开发了高性能的 JSON 库  sonic-rs。


  • sonic(Golang JSON 库):https://github.com/bytedance/sonic

  • sonic-cpp(C++ JSON 库):https://github.com/bytedance/sonic-cpp

  • sonic-rs(Rust JSON 库):https://github.com/cloudwego/sonic-rs


sonic-rs 目前支持的 JSON 功能比较齐全,基本对齐了 serde-json 的相关功能,并且提供更加丰富的功能和更多的高性能接口。sonic-rs 的主要功能特点有:


  • 基本兼容 Serde 生态,同时支持 Volo 中的 FastStr 类型

  • 支持动态类型编解码和按需解析

  • 支持 LazyVaue,RawNumber 等类型

  • 支持 UTF-8 校验和标准浮点数精度


在性能方面,我们基于 serde-rs 官方 benchmark (https://github.com/serde-rs/json-benchmark) 提供的 Rust 结构体和 JSON 数据,对 serde-json, simd-json 和 sonic-rs 在 Rust 结构体下的解析性能进行了测试,可以发现 sonic-rs 的性能是 simd-json 的 1.5~2 倍,是 serde-json 2 倍:


二、sonic-rs 优化实践


sonic-rs 的优化主要基于 SIMD,其中部分借鉴了其他 JSON 库,如 simd-json 的优化思路。SIMD (Single instruction, multiple data) 是一种并行优化技术,可以用一条指令,并行处理多个数据。如今大多数 CPU 已经支持了各种 SIMD 指令集。例如,x86_64 架构下的 SSE,AVX2,AVX512, aarch64 架构下的 neon 指令集等。使用 SIMD 指令优化之后,对于合适的任务,程序执行的指令数量会更少,因此性能会更好。


在整体设计上,sonic-rs 并没有采用 simd-json 那种二阶段解析的思路,主要将 SIMD 优化应用于 JSON 解析和序列化中的热点,包括字符串序列化、按需解析和浮点数解析等。

1. SIMD 优化字符串序列化


字符串序列化是 JSON 序列化的热点。序列化时,需要扫描字符串中的转义字符。对于较长的字符串,逐个字节判断转义字符的操作是比较耗时的,扫描转义字符非常适合使用 SIMD 来加速。


如果用 AVX2 指令来扫描转义字符,如下面代码所示。这段 SIMD 代码在 haswell 架构下面,开 O3 优化之后,其实只有六条 SIMD 指令,即 6 条 SIMD 指令可以一次性扫描 32 个字节。相比较标量代码来说,大大减少了程序指令的数量,从而减少了程序的执行时间。


2. SIMD 优化按需解析


很多业务场景只用到 JSON 中的部分字段,很适合按需解析,在解析时跳过不需要的 JSON 字段。在跳过 JSON 字段时,难点在于如何高效跳过 JSON 中的 object 和 array。


基于 JSON 中 object 和 array 括号必须匹配的语法规则,sonic-rs 使用 SIMD 实现了高效的括号匹配算法。先通过 SIMD 得到 json object 和 array 的 bitmap,然后通过计算括号的数量来跳过 object 和 array。当发现括号匹配时,就可以跳过该 object 或 array。


3. SIMD 优化浮点数解析


浮点数解析是 JSON 解析中的一个性能热点。在字节内部,我们发现 JSON 中大部分浮点数的尾数都比较长,也适合使用 SIMD 优化。如下图,对于一段长 16 个字节的浮点数尾数 "1234342112345678":


  • 先将这段字符串读取到向量寄存器里面,此时向量的每个数字还是 ASCII 码的值。

  • 其次,用向量的减法,逐个字节减去 ASCII 码 '0' 得到 v1。这时。v1 里面的数字已经是十进制。

  • 然后,继续对 v1 里面的各个数字用向量指令做两两乘加(高位乘以 10 再加上低位),得到 v2。v2 里面的各个数已经是十进制的两位数。

  • 以此类推,利用 SIMD 指令逐层累加,最终就得到 v16。v16 里面是一个 16 位数,即最终的尾数解析结果。

  • 最后,我们再用向量指令把 v16 转成 u64 类型。


整个解析过程,不用遍历浮点数尾数的每一个字符,就能完成浮点数尾数解析。


三、sonic-rs 现状和规划


sonic-rs 已经开源几个月了,目前迭代到了 0.3 版本,已经支持 Rust stable 版本,并且支持了 aarch64 架构。sonic-rs 沉淀了一些使用文档,用以帮助各方面的开发者:


  • Golang 迁移 Rust 用户使用 sonic-rs:https://github.com/cloudwego/sonic-rs/blob/main/docs/for_Golang_user_zh.md

  • Rust serde-json 用户迁移 sonic-rs:https://github.com/cloudwego/sonic-rs/blob/main/docs/serdejson_compatibility.md

  • 性能优化细节:https://github.com/cloudwego/sonic-rs/blob/main/docs/performance_zh.md


后续,sonic-rs 会在性能,易用性和稳定性上面继续打磨,预期会支持对 Bytes/FastStr 等常见数据类型的零拷贝解析,支持运动时检测 SIMD 指令等,欢迎感兴趣的开发者一起加入我们。


项目地址

GitHub:https://github.com/cloudwego

官网:www.cloudwego.io

2024-03-26 17:074739

评论

发布
暂无评论
发现更多内容

移动App的设计流程是怎样的?

InfoQ IT百科

有哪些好用的代码编辑器?

InfoQ IT百科

如何修改电脑文件格式?

InfoQ IT百科

主流的网站服务器架构有哪些?

InfoQ IT百科

现在常用的视频会议软件有哪些?

InfoQ IT百科

现在常用的在线协作文档软件有哪些?

InfoQ IT百科

WPS是什么软件?

InfoQ IT百科

做 App 还是小程序好?

InfoQ IT百科

如何优雅高效地管理公司文档?

小炮

文档 文档管理

App怎么做灰度发布?

InfoQ IT百科

怎么做SEO网站优化?

InfoQ IT百科

目前WPS支持在哪些设备上使用?

InfoQ IT百科

使用WPS需要注册/登录账号吗?

InfoQ IT百科

TASKCTL 作业流程无触发设计

敏捷调度TASKCTL

大数据 DevOps 分布式 自动化部署 ETL任务

WPS有哪些隐藏的使用小技巧?

InfoQ IT百科

如何部署自己的网站?

InfoQ IT百科

阿里云 云效一站式研发平台

阿里云云效

阿里云 DevOps 云原生 研发 一站式研发平台

有哪些适合程序员用的笔记应用?

InfoQ IT百科

注册域名后,怎么创建个人网站?

InfoQ IT百科

软件激活码是什么?

InfoQ IT百科

Java篇-序列化与反序列化

是老郭啊

Java 对象 序列化 反序列化

WordPress 是什么?

InfoQ IT百科

低代码开发平台能开发哪些应用?

InfoQ IT百科

安卓App和鸿蒙App有什么不同?

InfoQ IT百科

如何隐藏电脑上的文件?

InfoQ IT百科

从杀慢查询入手来预防 MySQL 雪崩的办法

Qunar技术沙龙

dba

怎么让网站在搜索结果中排更前?

InfoQ IT百科

如何添加字体?

InfoQ IT百科

一个WPS账号可以在多个设备同时登陆吗?

InfoQ IT百科

有哪些比较靠谱的低代码开发平台?

InfoQ IT百科

高性能 Rust JSON 库 sonic-rs优化实践_编程语言_刘强_InfoQ精选文章