原生 json 包效率低

原因

原生 json 包主要是用到了reflect,所以比较慢,推荐优先使用 json-iterator 包解析 json。

代码分析

测试环境:macbook pro macos

Go 版本: 1.14

json-iterator 版本: v1.1.9

测试解析单次大 json 的情况

循环次数/耗时 encoding/json json-iterator
json长度10 239.665µs 162.146µs
json长度50 231.41µs 150.292µs
json长度500 735.36µs 258.523µs
json长度1,000 1.346841ms 379.458µs
json长度10,000 132.953435ms 29.646291ms

测试解析并发和大 json 的情况

循环次数/耗时 encoding/json json-iterator
循环10次,json长度100 1.427445ms 413.796µs
循环50次,json长度500 32.165554ms 6.099719ms
循环100次,json长度1,000 131.037902ms 23.466147ms
循环1,000次,json长度10,000 12.451799096s 2.631567452s
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package main

import (
    "fmt"
    "strings"
    "time"
    "encoding/json"
    jsoniter "github.com/json-iterator/go"
)

// 测试解析 json 的情况(可测试高并发和大json等情况)
func main() {
    num := 500 // json 长度
    num2 := 50 // 循环解析次数

    var builder strings.Builder
    builder.WriteString("[")
    for i := 0; i < num; i++ {
        if i != 0 {
            builder.WriteString(",")
        }
        builder.WriteString("{\"a\":100,\"b\":1234567890123456789,\"c\":\"\",\"d\":1.2}")
    }
    builder.WriteString("]")
    jsonData := builder.String()

    start := time.Now()
    for j := 0; j < num2; j++ {
        test_json(jsonData, true)
    }
    durationJson := time.Since(start)

    start = time.Now()
    for j := 0; j < num2; j++ {
        test_json(jsonData, false)
    }
    durationJsoniter := time.Since(start)

    fmt.Println("原生json耗时:", durationJson)
    fmt.Println("jsoniter耗时:", durationJsoniter)
}

func test_json(jsonData string, flag bool) {
    // 定义 json 结构通用类型
    // var m []interface{}

    // 定义 json 结构特定类型
    type mS struct {
        A uint32  `json:"a"`
        B uint64  `json:"b"`
        C string  `json:"c"`
        D float32 `json:"d"`
    }
    var m []mS

    if flag {
        if err := json.Unmarshal([]byte(jsonData), &m); err != nil {
            fmt.Println("Unmarshal error: ", err)
        }
    } else {
        if err := jsoniter.Unmarshal([]byte(jsonData), &m); err != nil {
            fmt.Println("Unmarshal error: ", err)
        }
    }
}