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