Optimize encoding for byteSlice type

This commit is contained in:
Masaaki Goshima 2020-09-15 23:22:35 +09:00
parent 6cac23acc3
commit 92fb386db5
2 changed files with 27 additions and 47 deletions

View File

@ -3,6 +3,7 @@ package json
import (
"bytes"
"encoding"
"encoding/base64"
"io"
"math"
"reflect"
@ -310,6 +311,22 @@ func (e *Encoder) encodeString(s string) {
}
}
func (e *Encoder) encodeByteSlice(b []byte) {
encodedLen := base64.StdEncoding.EncodedLen(len(b))
e.encodeByte('"')
pos := len(e.buf)
remainLen := cap(e.buf[pos:])
var buf []byte
if remainLen > encodedLen {
buf = e.buf[pos : pos+encodedLen]
} else {
buf = make([]byte, encodedLen)
}
base64.StdEncoding.Encode(buf, b)
e.encodeBytes(buf)
e.encodeByte('"')
}
func (e *Encoder) encodeByte(b byte) {
e.buf = append(e.buf, b)
}

View File

@ -99,13 +99,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
if ptr == 0 || header.Data == 0 {
e.encodeNull()
} else {
b := e.ptrToBytes(ptr)
encodedLen := base64.StdEncoding.EncodedLen(len(b))
e.encodeByte('"')
buf := make([]byte, encodedLen)
base64.StdEncoding.Encode(buf, b)
e.encodeBytes(buf)
e.encodeByte('"')
e.encodeByteSlice(e.ptrToBytes(ptr))
}
code = code.next
case opInterface:
@ -1151,10 +1145,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
} else {
e.encodeByte('{')
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset))
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(e.ptrToBytes(ptr + code.offset))
code = code.next
}
case opStructFieldPtrAnonymousHeadBytes:
@ -1166,10 +1157,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
code = code.end
} else {
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset))
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(e.ptrToBytes(ptr + code.offset))
code = code.next
}
case opStructFieldPtrHeadArray:
@ -2347,10 +2335,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
code = code.nextField
} else {
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(v)
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(v)
code = code.next
}
}
@ -2370,10 +2355,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
code = code.nextField
} else {
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(v)
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(v)
code = code.next
}
}
@ -3459,12 +3441,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
} else {
e.encodeByte('{')
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(
e.ptrToBytes(ptr + code.offset),
)
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(e.ptrToBytes(ptr + code.offset))
code = code.next
}
case opStructFieldPtrAnonymousHeadStringTagBytes:
@ -3479,12 +3456,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
code = code.end.next
} else {
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(
e.ptrToBytes(ptr + code.offset),
)
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(e.ptrToBytes(ptr + code.offset))
code = code.next
}
case opStructFieldPtrHeadStringTagMarshalJSON:
@ -4088,10 +4060,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
}
ptr := load(ctxptr, code.headIdx)
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset))
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(e.ptrToBytes(ptr + code.offset))
code = code.next
case opStructFieldMarshalJSON:
if e.buf[len(e.buf)-1] != '{' {
@ -4659,10 +4628,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
e.encodeByte(',')
}
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(v)
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(v)
}
code = code.next
case opStructFieldOmitEmptyMarshalJSON:
@ -5211,10 +5177,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
e.encodeByte(',')
}
e.encodeBytes(code.key)
s := base64.StdEncoding.EncodeToString(v)
e.encodeByte('"')
e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s)))
e.encodeByte('"')
e.encodeByteSlice(v)
code = code.next
case opStructFieldStringTagMarshalJSON:
ptr := load(ctxptr, code.headIdx)