From a6276c4d8ef0c87ee607392177a1040a86217886 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Mon, 31 Aug 2020 03:14:37 +0900 Subject: [PATCH] Optimize opcode.idx and seenPtr --- encode.go | 22 ++++++----- encode_compile.go | 51 ++++++++++++++----------- encode_context.go | 7 +--- encode_opcode.go | 97 ++++++++++++++++++++++++++--------------------- encode_vm.go | 21 +++++----- 5 files changed, 104 insertions(+), 94 deletions(-) diff --git a/encode.go b/encode.go index eb2f1e3..556bd57 100644 --- a/encode.go +++ b/encode.go @@ -164,9 +164,9 @@ func (e *Encoder) encode(v interface{}) error { } ctx := codeSet.ctx.Get().(*encodeRuntimeContext) p := uintptr(header.ptr) - ctx.reset() ctx.init(p) - err := e.run(ctx, code) + seenPtr := map[uintptr]struct{}{} + err := e.run(ctx, seenPtr, code) if e.enabledIndent { codeSet.codeIndent.Put(code) } else { @@ -210,8 +210,7 @@ func (e *Encoder) encode(v interface{}) error { ctx: sync.Pool{ New: func() interface{} { return &encodeRuntimeContext{ - ptrs: make([]uintptr, codeLength), - seenPtr: map[uintptr]struct{}{}, + ptrs: make([]uintptr, codeLength), } }, }, @@ -219,19 +218,22 @@ func (e *Encoder) encode(v interface{}) error { cachedOpcode.set(typeptr, codeSet) p := uintptr(header.ptr) ctx := codeSet.ctx.Get().(*encodeRuntimeContext) - ctx.reset() ctx.init(p) + + var c *opcode if e.enabledIndent { - err := e.run(ctx, codeIndent) - codeSet.ctx.Put(ctx) - return err + c = codeIndent + } else { + c = code } - if err := e.run(ctx, code); err != nil { + + seenPtr := map[uintptr]struct{}{} + if err := e.run(ctx, seenPtr, c); err != nil { codeSet.ctx.Put(ctx) return err } codeSet.ctx.Put(ctx) - return err + return nil } func (e *Encoder) encodeInt(v int) { diff --git a/encode_compile.go b/encode_compile.go index c2e6ed7..eb98048 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -267,11 +267,12 @@ func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) { func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) { code := (*opcode)(unsafe.Pointer(&interfaceCode{ opcodeHeader: &opcodeHeader{ - op: opInterface, - typ: ctx.typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, - next: newEndOp(ctx), + op: opInterface, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, + next: newEndOp(ctx), }, root: ctx.root, })) @@ -588,11 +589,12 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode { c := (*opcode)(unsafe.Pointer(&recursiveCode{ opcodeHeader: &opcodeHeader{ - op: opStructFieldRecursive, - typ: ctx.typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, - next: newEndOp(ctx), + op: opStructFieldRecursive, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, + next: newEndOp(ctx), }, jmp: code, })) @@ -726,7 +728,7 @@ func (e *Encoder) optimizeAnonymousFields(head *structFieldCode) { if codeType == codeStructField { if e.isNotExistsField(code.next.toStructFieldCode()) { code.next = code.nextField - diff := code.next.idx - code.idx + diff := code.next.displayIdx - code.displayIdx for i := 0; i < diff; i++ { code.next.decOpcodeIndex() } @@ -763,7 +765,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value } else if f.op == opStructEnd { f.op = opStructAnonymousEnd } else if existsKey { - diff := f.nextField.idx - f.idx + diff := f.nextField.displayIdx - f.displayIdx for i := 0; i < diff; i++ { f.nextField.decOpcodeIndex() } @@ -814,7 +816,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s // head operation fieldPair.curField.op = opStructFieldAnonymousHead } else { - diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx + diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx for i := 0; i < diff; i++ { fieldPair.curField.nextField.decOpcodeIndex() } @@ -831,7 +833,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s // head operation fieldPair.curField.op = opStructFieldAnonymousHead } else { - diff := fieldPair.curField.nextField.idx - fieldPair.curField.idx + diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx for i := 0; i < diff; i++ { fieldPair.curField.nextField.decOpcodeIndex() } @@ -919,10 +921,11 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, key := fmt.Sprintf(`"%s":`, tag.key) fieldCode := &structFieldCode{ opcodeHeader: &opcodeHeader{ - typ: valueCode.typ, - idx: fieldOpcodeIndex, - next: valueCode, - indent: ctx.indent, + typ: valueCode.typ, + displayIdx: fieldOpcodeIndex, + idx: uintptr(fieldOpcodeIndex) * 8, + next: valueCode, + indent: ctx.indent, }, anonymousKey: field.Anonymous, key: []byte(key), @@ -958,10 +961,11 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, if head == nil { head = &structFieldCode{ opcodeHeader: &opcodeHeader{ - op: opStructFieldHead, - typ: typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opStructFieldHead, + typ: typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, nextField: structEndCode, } @@ -972,7 +976,8 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, code = (*opcode)(unsafe.Pointer(head)) } - structEndCode.idx = ctx.opcodeIndex + structEndCode.displayIdx = ctx.opcodeIndex + structEndCode.idx = uintptr(ctx.opcodeIndex) * 8 ctx.incOpcodeIndex() if ctx.withIndent { diff --git a/encode_context.go b/encode_context.go index 0c7ee1b..ec30d68 100644 --- a/encode_context.go +++ b/encode_context.go @@ -59,12 +59,7 @@ func (c *encodeCompileContext) decOpcodeIndex() { } type encodeRuntimeContext struct { - ptrs []uintptr - seenPtr map[uintptr]struct{} -} - -func (c *encodeRuntimeContext) reset() { - c.seenPtr = map[uintptr]struct{}{} + ptrs []uintptr } func (c *encodeRuntimeContext) init(p uintptr) { diff --git a/encode_opcode.go b/encode_opcode.go index 0b49ed0..7cc4ae9 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -13,20 +13,22 @@ func copyOpcode(code *opcode) *opcode { } type opcodeHeader struct { - op opType - typ *rtype - idx int - indent int - next *opcode + op opType + typ *rtype + displayIdx int + idx uintptr + indent int + next *opcode } func (h *opcodeHeader) copy(codeMap map[uintptr]*opcode) *opcodeHeader { return &opcodeHeader{ - op: h.op, - typ: h.typ, - idx: h.idx, - indent: h.indent, - next: h.next.copy(codeMap), + op: h.op, + typ: h.typ, + displayIdx: h.displayIdx, + idx: h.idx, + indent: h.indent, + next: h.next.copy(codeMap), } } @@ -41,11 +43,12 @@ func newOpCode(ctx *encodeCompileContext, op opType) *opcode { func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { return &opcode{ opcodeHeader: &opcodeHeader{ - op: op, - typ: ctx.typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, - next: next, + op: op, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, + next: next, }, } } @@ -79,7 +82,7 @@ func (c *opcode) beforeLastCode() *opcode { func (c *opcode) length() int { var idx int for code := c; code.op != opEnd; { - idx = code.idx + idx = code.displayIdx switch code.op.codeType() { case codeArrayElem: code = code.toArrayElemCode().end @@ -96,7 +99,8 @@ func (c *opcode) length() int { func (c *opcode) decOpcodeIndex() { for code := c; code.op != opEnd; { - code.idx-- + code.displayIdx-- + code.idx -= 8 switch code.op.codeType() { case codeArrayElem: code = code.toArrayElemCode().end @@ -153,22 +157,22 @@ func (c *opcode) dump() string { indent := strings.Repeat(" ", code.indent) switch code.op.codeType() { case codeArrayElem: - codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) code = code.toArrayElemCode().end case codeSliceElem: - codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) code = code.toSliceElemCode().end case codeMapKey: - codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) code = code.toMapKeyCode().end case codeStructField: sf := code.toStructFieldCode() key := sf.displayKey offset := sf.offset - codes = append(codes, fmt.Sprintf("[%d]%s%s [%s:%d] ( %p )", code.idx, indent, code.op, key, offset, unsafe.Pointer(code))) + codes = append(codes, fmt.Sprintf("[%d]%s%s [%s:%d] ( %p )", code.displayIdx, indent, code.op, key, offset, unsafe.Pointer(code))) code = code.next default: - codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.idx, indent, code.op, unsafe.Pointer(code))) + codes = append(codes, fmt.Sprintf("[%d]%s%s ( %p )", code.displayIdx, indent, code.op, unsafe.Pointer(code))) code = code.next } } @@ -224,9 +228,10 @@ type sliceHeaderCode struct { func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode { return &sliceHeaderCode{ opcodeHeader: &opcodeHeader{ - op: opSliceHead, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opSliceHead, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } @@ -234,9 +239,10 @@ func newSliceHeaderCode(ctx *encodeCompileContext) *sliceHeaderCode { func newSliceElemCode(ctx *encodeCompileContext, size uintptr) *sliceElemCode { return &sliceElemCode{ opcodeHeader: &opcodeHeader{ - op: opSliceElem, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opSliceElem, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, size: size, } @@ -307,9 +313,10 @@ type arrayHeaderCode struct { func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode { return &arrayHeaderCode{ opcodeHeader: &opcodeHeader{ - op: opArrayHead, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opArrayHead, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, len: uintptr(alen), } @@ -318,8 +325,9 @@ func newArrayHeaderCode(ctx *encodeCompileContext, alen int) *arrayHeaderCode { func newArrayElemCode(ctx *encodeCompileContext, alen int, size uintptr) *arrayElemCode { return &arrayElemCode{ opcodeHeader: &opcodeHeader{ - op: opArrayElem, - idx: ctx.opcodeIndex, + op: opArrayElem, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, }, len: uintptr(alen), size: size, @@ -536,10 +544,11 @@ func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode { } return &mapHeaderCode{ opcodeHeader: &opcodeHeader{ - op: op, - typ: ctx.typ, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: op, + typ: ctx.typ, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } @@ -547,9 +556,10 @@ func newMapHeaderCode(ctx *encodeCompileContext, withLoad bool) *mapHeaderCode { func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { return &mapKeyCode{ opcodeHeader: &opcodeHeader{ - op: opMapKey, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opMapKey, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } @@ -557,9 +567,10 @@ func newMapKeyCode(ctx *encodeCompileContext) *mapKeyCode { func newMapValueCode(ctx *encodeCompileContext) *mapValueCode { return &mapValueCode{ opcodeHeader: &opcodeHeader{ - op: opMapValue, - idx: ctx.opcodeIndex, - indent: ctx.indent, + op: opMapValue, + displayIdx: ctx.opcodeIndex, + idx: uintptr(ctx.opcodeIndex) * 8, + indent: ctx.indent, }, } } diff --git a/encode_vm.go b/encode_vm.go index bc02567..e873ae8 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -11,17 +11,16 @@ import ( "unsafe" ) -func load(base uintptr, idx int) uintptr { - return *(*uintptr)(unsafe.Pointer(base + uintptr(idx)*8)) +func load(base uintptr, idx uintptr) uintptr { + return *(*uintptr)(unsafe.Pointer(base + idx)) } -func store(base uintptr, idx int, p uintptr) { - *(*uintptr)(unsafe.Pointer(base + uintptr(idx)*8)) = p +func store(base uintptr, idx uintptr, p uintptr) { + *(*uintptr)(unsafe.Pointer(base + idx)) = p } -func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { +func (e *Encoder) run(ctx *encodeRuntimeContext, seenPtr map[uintptr]struct{}, code *opcode) error { ctxptr := ctx.ptr() - seenPtr := ctx.seenPtr for { switch code.op { case opPtr: @@ -143,11 +142,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { c = code } ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, c.length()), - seenPtr: seenPtr, + ptrs: make([]uintptr, c.length()), } ctx.init(uintptr(header.ptr)) - if err := e.run(ctx, c); err != nil { + if err := e.run(ctx, seenPtr, c); err != nil { return err } code = ifaceCode.next @@ -566,11 +564,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { recursive.seenPtr = ptr recursiveCode := newRecursiveCode(recursive) ctx := &encodeRuntimeContext{ - ptrs: make([]uintptr, recursiveCode.length()), - seenPtr: seenPtr, + ptrs: make([]uintptr, recursiveCode.length()), } ctx.init(ptr) - if err := e.run(ctx, recursiveCode); err != nil { + if err := e.run(ctx, seenPtr, recursiveCode); err != nil { return err } code = recursive.next