Goccy/go-json 포장 시도

19900 단어 Goprogrammingtech
며칠 전 트위터에서 JSON 처리 패키지github.com/goccy/go-json를 봤는데 표준encoding/json로 교체할 수 있고 다른 호환 패키지보다 빠르다는 호언장담이 나왔다.


via “encoding/json
우선 정말 표준 포장github.com/goccy/go-json을 교체해 보세요.
마침 최근 JSON 형태로 그림문자 정보를 모아 포장encoding/json을 제작해 이 사진을 읽는 처리를 써봤다.spiegel-im-spiegel/emojis 표준 포장을 사용하면 이런 느낌이에요.
sample1.go
// +build run

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "os"
    "strings"

    emoji "github.com/spiegel-im-spiegel/emojis/json"
    "github.com/spiegel-im-spiegel/fetch"
)

func getEmojiSequenceJSON() ([]byte, error) {
    u, err := fetch.URL("https://raw.githubusercontent.com/spiegel-im-spiegel/emojis/main/json/emoji-sequences.json")
    if err != nil {
        return nil, err
    }
    resp, err := fetch.New().Get(u)
    if err != nil {
        return nil, err
    }
    return resp.DumpBodyAndClose()
}

func main() {
    b, err := getEmojiSequenceJSON()
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }
    list := []emoji.EmojiSequence{}
    if err := json.NewDecoder(bytes.NewReader(b)).Decode(&list); err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }

    fmt.Println("| Sequence | Shortcodes |")
    fmt.Println("| :------: | ---------- |")
    for _, ec := range list {
        var bldr strings.Builder
        for _, c := range ec.Shortcodes {
            bldr.WriteString(fmt.Sprintf(" `%s`", c))
        }
        fmt.Printf("| %v |%s |\n", ec.Sequence, bldr.String())
    }
}
이걸 돌려보면...
$ go run sample1.go
| Sequence | Shortcodes |
| :------: | ---------- |
| #️⃣ | `:hash:` `:keycap_#:` |
| *️⃣ | `:asterisk:` `:keycap_*:` `:keycap_star:` |
| 0️⃣ | `:zero:` `:keycap_0:` |
| 1️⃣ | `:one:` `:keycap_1:` |
...
.응, 응.
가방encoding/json으로 교체합니다.
sample2.go
import (
    "bytes"
-   "encoding/json"
    "fmt"
    "os"
    "strings"

+   "github.com/goccy/go-json"
    emoji "github.com/spiegel-im-spiegel/emojis/json"
    "github.com/spiegel-im-spiegel/fetch"
)
이 전선으로 한번 돌려보면...
출력은
$ go run sample2.go 
| Sequence | Shortcodes |
| :------: | ---------- |
| #️⃣ | `:hash:` `:keycap_#:` |
| *️⃣ | `:asterisk:` `:keycap_*:` `:keycap_star:` |
| 0️⃣ | `:zero:` `:keycap_0:` |
| 1️⃣ | `:one:` `:keycap_1:` |
...
과 같습니다.
그럼 이제 이 코드를 옮겨서 기준을 이동해 봅시다.이런 느낌 괜찮아요?
json2_test.go
package jsonbench

import (
    "bytes"
    "encoding/json"
    "testing"

    another "github.com/goccy/go-json"
    emoji "github.com/spiegel-im-spiegel/emojis/json"
    "github.com/spiegel-im-spiegel/fetch"
)

func getMustEmojiSequenceJSON() []byte {
    u, err := fetch.URL("https://raw.githubusercontent.com/spiegel-im-spiegel/emojis/main/json/emoji-sequences.json")
    if err != nil {
        panic(err)
    }
    resp, err := fetch.New().Get(u)
    if err != nil {
        panic(err)
    }
    b, err := resp.DumpBodyAndClose()
    if err != nil {
        panic(err)
    }
    return b
}

var jsonText = getMustEmojiSequenceJSON()

func BenchmarkDecodeOrgPkg(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = json.NewDecoder(bytes.NewReader(jsonText)).Decode(&([]emoji.EmojiSequence{}))
    }
}

func BenchmarkDecodeAnotherPkg(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = another.NewDecoder(bytes.NewReader(jsonText)).Decode(&([]emoji.EmojiSequence{}))
    }
}
이 조작을 실행하여 기존 환경에서 다음과 같은 결과를 얻었다.
$ go test -bench Decode -benchmem
goos: linux
goarch: amd64
pkg: json2
cpu: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz
BenchmarkDecodeOrgPkg-4                 99      11095017 ns/op     2257059 B/op       17398 allocs/op
BenchmarkDecodeAnotherPkg-4            352       3386700 ns/op      907342 B/op        6403 allocs/op
PASS
ok      json2    3.172s
표를 만들면 이런 느낌이에요.
매크로 패키지 사용
운행 시간
Alloc 치수
Alloc 횟수
github.com/goccy/go-json
11,095,017 ns/op
2,257,059 B/op
17,398 allocs/op
encoding/json
3,386,700 ns/op
907,342 B/op
6,403 allocs/op
두 분.자리랑 횟수가 먼저 달라요?그럼 차이가 있을 거야.실행 시간을 전체적으로 표준의 3할로 압축하다.
이것은 고려할 만한 가치가 있습니까?

저자 goccy 슬라이드


goccy/go-json

참고 자료


https://docs.google.com/presentation/d/1VCUPh21hrZRN-2kneQ07dxJPjgScSo3gsKESWlEBzIQ/
https://zenn.dev/spiegel/articles/20210113-fetch
https://zenn.dev/spiegel/articles/20210322-emoji-shortcode-for-markdown

좋은 웹페이지 즐겨찾기