[第三方库推荐] simdjson-go Golang 高性能 JSON 解析器,十倍于 encoding/JSON

simdjson-go

简介

这是 Golang 版本的 simdjson,一个高性能的 JSON 解析器。在架构上使用 SIMD 指令来获取每秒处理千兆 JSON 数据的性能。

大部分情况下,simdjson-go 差不多能有 40% 到 60% 于 simdjson 的速度。此速度也会比 Golang 官方的 encoding/json 快差不多十倍。

特性

simdjson-go 是一个验证解析器,这意味着它会验证和检查数值、布尔值等。因此,这些值在解析后可用作适当的 intfloat64表示。

此外simdjson-go 具有以下功能:

  • 没有4 GB对象限制
  • 支持 ndjson (换行分隔的json)
  • 适当的内存管理
  • 纯 Go (不需要cgo)

与 simdjson 的性能对比

基于相同的 JSON 测试文件集,下图显示了 simdjsonsimdjson-go之间的比较:

simdjson-vs-go-comparison

这些数字是在配备 3.1 GHz Intel Core i7 的 MacBook Pro 上测量的。此外,为了使它公平地进行比较,将常数  GOLANG_NUMBER_PARSING 设为 false (默认为 true),以便使用相同的数字解析函数(以某些精度为代价更快;参见下文)。

encoding/json 和 json-iterator/go 性能对比

以下它是基于同一组JSON测试文件与Golang标准包 encoding/json 的性能比较。

$ benchcmp                    encoding_json.txt      simdjson-go.txt
benchmark                     old MB/s               new MB/s         speedup
BenchmarkApache_builds-8      106.77                  948.75           8.89x
BenchmarkCanada-8              54.39                  519.85           9.56x
BenchmarkCitm_catalog-8       100.44                 1565.28          15.58x
BenchmarkGithub_events-8      159.49                  848.88           5.32x
BenchmarkGsoc_2018-8          152.93                 2515.59          16.45x
BenchmarkInstruments-8         82.82                  811.61           9.80x
BenchmarkMarine_ik-8           48.12                  422.43           8.78x
BenchmarkMesh-8                49.38                  371.39           7.52x
BenchmarkMesh_pretty-8         73.10                  784.89          10.74x
BenchmarkNumbers-8            160.69                  434.85           2.71x
BenchmarkRandom-8              66.56                  615.12           9.24x
BenchmarkTwitter-8             79.05                 1193.47          15.10x
BenchmarkTwitterescaped-8      83.96                  536.19           6.39x
BenchmarkUpdate_center-8       73.92                  860.52          11.64x

那么 simdjson-go 使用较少的额外内存和分配。

这是它和另一个包 json-iterator/go 的基准测试比较:

$ benchcmp                    json-iterator.txt      simdjson-go.txt
benchmark                     old MB/s               new MB/s         speedup
BenchmarkApache_builds-8      154.65                  948.75           6.13x
BenchmarkCanada-8              40.34                  519.85          12.89x
BenchmarkCitm_catalog-8       183.69                 1565.28           8.52x
BenchmarkGithub_events-8      170.77                  848.88           4.97x
BenchmarkGsoc_2018-8          225.13                 2515.59          11.17x
BenchmarkInstruments-8        120.39                  811.61           6.74x
BenchmarkMarine_ik-8           61.71                  422.43           6.85x
BenchmarkMesh-8                50.66                  371.39           7.33x
BenchmarkMesh_pretty-8         90.36                  784.89           8.69x
BenchmarkNumbers-8             52.61                  434.85           8.27x
BenchmarkRandom-8              85.87                  615.12           7.16x
BenchmarkTwitter-8            139.57                 1193.47           8.55x
BenchmarkTwitterescaped-8     102.28                  536.19           5.24x
BenchmarkUpdate_center-8      101.41                  860.52           8.49x

使用方法

执行一下命令安装 simdjson-go

$ go get github.com/minio/simdjson-go

为了解析JSON字节流, 你也可以调用 simdjson.Parse() 或者 simdjson.ParseND()解析换行符分隔的 JSON 文件。这两个函数都返回一个 ParsedJson 结构,可以通过该结构调用 Iter() 来浏览 JSON 对象。

使用 Iter 类型, 你可以调用 Advance() 去迭代遍历类型(原文是tape,感觉有点不对。),如下所示:

for {
    typ := iter.Advance()

    switch typ {
    case simdjson.TypeRoot:
        if typ, tmp, err = iter.Root(tmp); err != nil {
            return
        }

        if typ == simdjson.TypeObject {
            if obj, err = tmp.Object(obj); err != nil {
                return
            }

            e := obj.FindKey(key, &elem)
            if e != nil && elem.Type == simdjson.TypeString {
                v, _ := elem.Iter.StringBytes()
                fmt.Println(string(v))
            }
        }

    default:
        return
    }
}

在示例子目录中可以找到更多示例,并且可以在 godoc 上找到更多文档。

要求

simdjson-go 具有以下要求:

  • 需要同时具有AVX2和CLMUL的CPU(从2013年起Haswell应该用于Intel,对于AMD而言,一个 Ryzen/EPIC CPU(2017年第一季度)就足够了)。可以使用提供的 SupportedCPU()函数进行检查。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://github.com/minio/simdjson-go

译文地址:https://learnku.com/go/t/41043

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!