mirror of https://github.com/goccy/go-json.git
Merge pull request #68 from goccy/feature/add-benchmark
Optimize access to opcodeMap
This commit is contained in:
commit
0e0bf702c1
33
encode.go
33
encode.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,31 +34,32 @@ const (
|
||||||
bufSize = 1024
|
bufSize = 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
type opcodeMap struct {
|
|
||||||
sync.Map
|
|
||||||
}
|
|
||||||
|
|
||||||
type opcodeSet struct {
|
type opcodeSet struct {
|
||||||
codeIndent *opcode
|
codeIndent *opcode
|
||||||
code *opcode
|
code *opcode
|
||||||
ctx sync.Pool
|
ctx sync.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *opcodeMap) get(k uintptr) *opcodeSet {
|
func loadOpcodeMap() map[uintptr]*opcodeSet {
|
||||||
if v, ok := m.Load(k); ok {
|
p := atomic.LoadPointer(&cachedOpcode)
|
||||||
return v.(*opcodeSet)
|
return *(*map[uintptr]*opcodeSet)(unsafe.Pointer(&p))
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *opcodeMap) set(k uintptr, op *opcodeSet) {
|
func storeOpcodeSet(typ uintptr, set *opcodeSet, m map[uintptr]*opcodeSet) {
|
||||||
m.Store(k, op)
|
newOpcodeMap := make(map[uintptr]*opcodeSet, len(m)+1)
|
||||||
|
newOpcodeMap[typ] = set
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
newOpcodeMap[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic.StorePointer(&cachedOpcode, *(*unsafe.Pointer)(unsafe.Pointer(&newOpcodeMap)))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
encPool sync.Pool
|
encPool sync.Pool
|
||||||
codePool sync.Pool
|
codePool sync.Pool
|
||||||
cachedOpcode opcodeMap
|
cachedOpcode unsafe.Pointer // map[uintptr]*opcodeSet
|
||||||
marshalJSONType reflect.Type
|
marshalJSONType reflect.Type
|
||||||
marshalTextType reflect.Type
|
marshalTextType reflect.Type
|
||||||
)
|
)
|
||||||
|
@ -72,7 +74,6 @@ func init() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cachedOpcode = opcodeMap{}
|
|
||||||
marshalJSONType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
marshalJSONType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
||||||
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||||
}
|
}
|
||||||
|
@ -175,7 +176,8 @@ func (e *Encoder) encode(v interface{}) error {
|
||||||
typ := header.typ
|
typ := header.typ
|
||||||
|
|
||||||
typeptr := uintptr(unsafe.Pointer(typ))
|
typeptr := uintptr(unsafe.Pointer(typ))
|
||||||
if codeSet := cachedOpcode.get(typeptr); codeSet != nil {
|
opcodeMap := loadOpcodeMap()
|
||||||
|
if codeSet, exists := opcodeMap[typeptr]; exists {
|
||||||
var code *opcode
|
var code *opcode
|
||||||
if e.enabledIndent {
|
if e.enabledIndent {
|
||||||
code = codeSet.codeIndent
|
code = codeSet.codeIndent
|
||||||
|
@ -224,7 +226,8 @@ func (e *Encoder) encode(v interface{}) error {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cachedOpcode.set(typeptr, codeSet)
|
|
||||||
|
storeOpcodeSet(typeptr, codeSet, opcodeMap)
|
||||||
p := uintptr(header.ptr)
|
p := uintptr(header.ptr)
|
||||||
ctx := codeSet.ctx.Get().(*encodeRuntimeContext)
|
ctx := codeSet.ctx.Get().(*encodeRuntimeContext)
|
||||||
ctx.init(p)
|
ctx.init(p)
|
||||||
|
|
Loading…
Reference in New Issue