Open
Description
I've tried a few different combinations of types and interfaces to encode the same thing. Interestingly, there's a 30% speed variation depending on what I'm calling, which seems extreme. I'd expect the same performance, independent of where the data enters into the encoder.
BenchmarkMarshal2String-12 232 5220942 ns/op
BenchmarkMarshal2RawJSON-12 283 4093803 ns/op
BenchmarkMarshal2Texter-12 222 5399327 ns/op
BenchmarkMarshal2Jsoner-12 265 4748703 ns/op
BenchmarkMarshal2Jsoner2-12 271 4422361 ns/op
package test
import (
"bytes"
"encoding/hex"
"encoding/json"
"testing"
json2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
)
func BenchmarkMarshalString(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
str := hex.EncodeToString(src)
b.ResetTimer()
for i := 0; i < b.N; i++ {
json.Marshal(str)
}
}
func BenchmarkMarshal2String(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
str := hex.EncodeToString(src)
b.ResetTimer()
for i := 0; i < b.N; i++ {
json2.Marshal(str)
}
}
func BenchmarkMarshalRawJSON(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
msg := json.RawMessage(`"` + hex.EncodeToString(src) + `"`)
b.ResetTimer()
for i := 0; i < b.N; i++ {
json.Marshal(msg)
}
}
func BenchmarkMarshal2RawJSON(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
msg := json.RawMessage(`"` + hex.EncodeToString(src) + `"`)
b.ResetTimer()
for i := 0; i < b.N; i++ {
json2.Marshal(msg)
}
}
func BenchmarkMarshalTexter(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
txt := &Texter{str: hex.EncodeToString(src)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
json.Marshal(txt)
}
}
func BenchmarkMarshal2Texter(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
txt := &Texter{str: hex.EncodeToString(src)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
json2.Marshal(txt)
}
}
func BenchmarkMarshalJsoner(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
jsn := &Jsoner{str: hex.EncodeToString(src)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
json.Marshal(jsn)
}
}
func BenchmarkMarshal2Jsoner(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
jsn := &Jsoner{str: hex.EncodeToString(src)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
json2.Marshal(jsn)
}
}
func BenchmarkMarshal2Jsoner2(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
jsn := &Jsoner2{str: hex.EncodeToString(src)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
json2.Marshal(jsn)
}
}
func BenchmarkMarshalCopyString(b *testing.B) {
src := bytes.Repeat([]byte{'0'}, 4194304)
str := hex.EncodeToString(src)
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf := make([]byte, len(str)+2)
buf[0] = '"'
copy(buf[1:], str)
buf[len(buf)-1] = '"'
}
}
type Texter struct {
str string
}
func (t Texter) MarshalText() ([]byte, error) {
return []byte(t.str), nil
}
type Jsoner struct {
str string
}
func (j Jsoner) MarshalJSON() ([]byte, error) {
return []byte(`"` + j.str + `"`), nil
}
type Jsoner2 struct {
str string
}
func (j Jsoner2) MarshalJSONV2(enc *jsontext.Encoder, opts json2.Options) error {
return enc.WriteValue([]byte(`"` + j.str + `"`))
}