Code前端首页关于Code前端联系我们

Go语言顶级JSON解析:Sonic

terry 2年前 (2023-09-24) 阅读数 78 #后端开发

Sonic是Go语言的JSON解析库,源码为字节跳动。根据官方的说法:

  • Sonic是一个非常快的JSON序列化/反序列化库,通过JIT(即时翻译)和SIMD(单指令流多数据流)加速。
  • Sonic 在所有 json 大小和所有使用情况下都表现最佳。

自2021年7月Sonic发布抖音以来,今日头条等公司纷纷采用Sonic,为字节跳动节省了数十万CPU核心(不少钱~)。

我们来看看Sonic相对于其他JSON解析库的优势以及常见的使用示例。

Sonic R&K 背景

  • Go 附带了一个标准的 JSON 库:encoding/json。还有很多优秀的第三方库,如:Json-iterator、Easyjson、Gjson、Sjson 等。其中 Json-iterator 是最受欢迎的。欢迎(12.3+k 星)。
  • 字节根据JSON样本的key数量和深度分为三个级别:
    • small(小):400B,11个key,深度3层;
    • medium(中):110KB,300+键,4层深(包含大量嵌套JSON字符串的真实业务数据);
    • large(大型):550 KB,超过 10,000 个密钥,6 层深。

测试结果如下: Go语言JSON解析届顶流:Sonic结果显示:目前这些JSON库都无法在所有场景下保持最佳性能。甚至一般编程中最常用的第三方库Json-iterator。解码和大数据场景下的性能无法满足字节需求。

JSON库的基础编解码性能固然重要,但不同场景的最佳兼容更关键——于是Byte走上了自研JSON库的道路。? ,深度4层)Go语言JSON解析届顶流:Sonic大数据(500KB),10000+密钥深度6层

可以看到Sonic在大多数场景下都有明显的优势:

  • 平均编码能力比J高240%son-iter ,平均解码性能比Json迭代器好110%;
  • 一键编辑能力比Sjson强75%。
  • 在生产环境中,Sonic也发现了很好的优势,业务高峰时使用的核心数几乎减少了♓:
Go语言JSON解析届顶流:SonicYte业务CPU占用率对比(核心数)。 *Sonic*上线前后

根据上面的测试对比结果,我们很难不使用Sonic来优化我们的业务,提高我们自己系统的效率~

常见的Sonic使用场景

分析映射类型

要将 JSON 数据解析为映射类型,请使用 Sonic 到 Methodia:

  • 只需调用 Sonic 的 Unmarshal 函数并将 JSON 数据和空映射作为参数传递即可。 ?并将 JSON 数据和结构作为参数传递给 Unmarshal 函数。

例如:

package main

import (
 "github.com/bytedance/sonic"
 "fmt"
)

func main() {
    type Person struct {
        Name string `json:"name"`
        Age int `json:"age"`
    }

    var jsonStr = `{"name": "Harper", "age": 20}`
    var person Person

    err := sonic.Unmarshal([]byte(jsonStr), &person)
    if err != nil {
        fmt.Println("解析失败:", err)
    }

    fmt.Println(person.Name, person.Age)
}
Go语言JSON解析届顶流:Sonic执行结果

解析嵌套 JSON 数据

Sonic 可以解析嵌套 JSON 数据,其实原因与上面“解析为结构类型”相同,例如:

package main

import (
 "github.com/bytedance/sonic"
 "fmt"
)

func main() {
    var jsonStr = `{"name": "Harper", "age": 30, "address": {"city": "HaiDian Beijing", "country": "China"}}`

    type Address struct {
        City string `json:"city"`
        Country string `json:"country"`
    }

    type Person struct {
        Name string `json:"name"`
        Age int `json:"age"`
        Address Address `json:"address"`
    }

    var person Person
    err := sonic.Unmarshal([]byte(jsonStr), &person)
    if err != nil {
        fmt.Println("解析失败:", err)
    }
    
    fmt.Println(person.Name, person.Age, person.Address.City, person.Address.Country)
}
Go语言JSON解析届顶流:Sonic执行result

组织矩阵类型

Sonic 还可以解析表格类型 JSON 数据,例如:

package main

import (
 "github.com/bytedance/sonic"
 "fmt"
)

func main() {
    var jsonStr = `[{"name": "Harper", "age": 33}, {"name": "Bella", "age": 34}]`

    type Person struct {
        Name string `json:"name"`
        Age int `json:"age"`
    }

    var persons []Person
    err := sonic.Unmarshal([]byte(jsonStr), &persons)
    if err != nil {
        fmt.Println("解析失败:", err)
    }
    
    for _, person := range persons {
        fmt.Println(person.Name, person.Age)
    }
}
Go语言JSON解析届顶流:Sonic性能结果

性能结果

Sonic 库性能高。丰富的JSON解析API,包括解析成map、struct、嵌套JSON数据、数组类型等,几乎涵盖了我们工作中的所有应用场景。

尤其是在大数据解析场景下,如果我们的系统在解析JSON数据时遇到瓶颈,不妨尝试一下Sonic看看影响。毕竟切换起来还是很方便的。和Json迭代器一样,切换成本很低。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门