go-json/benchmarks/slow_reader_test.go

79 lines
1.8 KiB
Go
Raw Permalink Normal View History

2021-05-03 10:25:26 +03:00
package benchmark
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"testing"
gojson "github.com/goccy/go-json"
)
// Benchmark decoding from a slow io.Reader that never fills the buffer completely
func Benchmark_Decode_SlowReader_EncodingJson(b *testing.B) {
var expected LargePayload
if err := json.Unmarshal(LargeFixture, &expected); err != nil {
b.Fatal(err)
}
for _, chunkSize := range [5]int{16384, 4096, 1024, 256, 64} {
b.Run(fmt.Sprintf("chunksize %v", chunkSize), func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
index = 0
var got LargePayload
if err := json.NewDecoder(slowReader{chunkSize: chunkSize}).Decode(&got); err != nil {
b.Fatal(err)
}
if !reflect.DeepEqual(expected, got) {
b.Fatalf("failed to decode. expected:[%+v] but got:[%+v]", expected, got)
}
}
})
}
}
func Benchmark_Decode_SlowReader_GoJson(b *testing.B) {
var expected LargePayload
if err := json.Unmarshal(LargeFixture, &expected); err != nil {
b.Fatal(err)
}
for _, chunkSize := range []int{16384, 4096, 1024, 256, 64} {
b.Run(fmt.Sprintf("chunksize %v", chunkSize), func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
index = 0
var got LargePayload
if err := gojson.NewDecoder(slowReader{chunkSize: chunkSize}).Decode(&got); err != nil {
b.Fatal(err)
}
if !reflect.DeepEqual(expected, got) {
b.Fatalf("failed to decode. expected:[%+v] but got:[%+v]", expected, got)
}
}
})
}
}
type slowReader struct {
chunkSize int
}
var index int
func (s slowReader) Read(p []byte) (n int, err error) {
smallBuf := make([]byte, Min(s.chunkSize, len(p)))
x := bytes.NewReader(LargeFixture)
n, err = x.ReadAt(smallBuf, int64(index))
index += n
copy(p, smallBuf)
return
}
func Min(x, y int) int {
if x < y {
return x
}
return y
}