Skip to content

Commit

Permalink
Add type addrShift to enable bigger encoder/decoder cache
Browse files Browse the repository at this point in the history
Change-Id: I630fa501f3b96702b69a40bc0b2f79f4db2a57eb
  • Loading branch information
jxskiss committed May 10, 2021
1 parent 835c00e commit 7e03a13
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 12 deletions.
21 changes: 17 additions & 4 deletions codec.go
Expand Up @@ -16,6 +16,7 @@ var (
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
baseTypeAddr uintptr
maxTypeAddr uintptr
typeAddrShift uintptr
)

//go:linkname typelinks reflect.typelinks
Expand All @@ -35,8 +36,10 @@ func setupCodec() error {
section := sections[0]
offset := offsets[0]
var (
min uintptr = uintptr(^uint(0))
max uintptr = 0
min uintptr = uintptr(^uint(0))
max uintptr = 0
isAligned64 = true
isAligned32 = true
)
for i := 0; i < len(offset); i++ {
typ := (*rtype)(rtypeOff(section, offset[i]))
Expand All @@ -56,15 +59,25 @@ func setupCodec() error {
max = addr
}
}

// check every address is aligned from the base address
isAligned64 = isAligned64 && (addr-min)&63 == 0
isAligned32 = isAligned32 && (addr-min)&31 == 0
}
addrRange := max - min
if addrRange == 0 {
return fmt.Errorf("failed to get address range of types")
}
if addrRange > maxAcceptableTypeAddrRange {
if isAligned64 {
typeAddrShift = 6
} else if isAligned32 {
typeAddrShift = 5
}
cacheSize := addrRange >> typeAddrShift
if cacheSize > maxAcceptableTypeAddrRange {
return fmt.Errorf("too big address range %d", addrRange)
}
cachedDecoder = make([]decoder, addrRange)
cachedDecoder = make([]decoder, cacheSize)
baseTypeAddr = min
maxTypeAddr = max
return nil
Expand Down
13 changes: 13 additions & 0 deletions codec_go16_test.go
@@ -0,0 +1,13 @@
// +build go1.16

package json

import (
"testing"
)

func TestTypeAddressAligned32(t *testing.T) {
if typeAddrShift != 5 {
t.Fatalf("unexpected type address shift %d, want 5", typeAddrShift)
}
}
2 changes: 1 addition & 1 deletion decode_compile_norace.go
Expand Up @@ -10,7 +10,7 @@ func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
}

index := typeptr - baseTypeAddr
index := (typeptr - baseTypeAddr) >> typeAddrShift
if dec := cachedDecoder[index]; dec != nil {
return dec, nil
}
Expand Down
2 changes: 1 addition & 1 deletion decode_compile_race.go
Expand Up @@ -15,7 +15,7 @@ func decodeCompileToGetDecoder(typ *rtype) (decoder, error) {
return decodeCompileToGetDecoderSlowPath(typeptr, typ)
}

index := typeptr - baseTypeAddr
index := (typeptr - baseTypeAddr) >> typeAddrShift
decMu.RLock()
if dec := cachedDecoder[index]; dec != nil {
decMu.RUnlock()
Expand Down
2 changes: 1 addition & 1 deletion internal/encoder/compiler.go
Expand Up @@ -27,7 +27,7 @@ func init() {
if typeAddr == nil {
typeAddr = &runtime.TypeAddr{}
}
cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange)
cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift)
}

func loadOpcodeMap() map[uintptr]*OpcodeSet {
Expand Down
2 changes: 1 addition & 1 deletion internal/encoder/compiler_norace.go
Expand Up @@ -12,7 +12,7 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
if typeptr > typeAddr.MaxTypeAddr {
return compileToGetCodeSetSlowPath(typeptr)
}
index := typeptr - typeAddr.BaseTypeAddr
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
return codeSet, nil
}
Expand Down
2 changes: 1 addition & 1 deletion internal/encoder/compiler_race.go
Expand Up @@ -15,7 +15,7 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
if typeptr > typeAddr.MaxTypeAddr {
return compileToGetCodeSetSlowPath(typeptr)
}
index := typeptr - typeAddr.BaseTypeAddr
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
setsMu.RLock()
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
setsMu.RUnlock()
Expand Down
19 changes: 16 additions & 3 deletions internal/runtime/type.go
Expand Up @@ -19,6 +19,7 @@ type TypeAddr struct {
BaseTypeAddr uintptr
MaxTypeAddr uintptr
AddrRange uintptr
AddrShift uintptr
}

var (
Expand Down Expand Up @@ -49,8 +50,10 @@ func AnalyzeTypeAddr() *TypeAddr {
section := sections[0]
offset := offsets[0]
var (
min uintptr = uintptr(^uint(0))
max uintptr = 0
min uintptr = uintptr(^uint(0))
max uintptr = 0
isAligned64 = true
isAligned32 = true
)
for i := 0; i < len(offset); i++ {
typ := (*Type)(rtypeOff(section, offset[i]))
Expand All @@ -70,18 +73,28 @@ func AnalyzeTypeAddr() *TypeAddr {
max = addr
}
}
isAligned64 = isAligned64 && (addr-min)&63 == 0
isAligned32 = isAligned32 && (addr-min)&31 == 0
}
addrRange := max - min
if addrRange == 0 {
return nil
}
if addrRange > maxAcceptableTypeAddrRange {
var addrShift uintptr
if isAligned64 {
addrShift = 6
} else if isAligned32 {
addrShift = 5
}
cacheSize := addrRange >> addrShift
if cacheSize > maxAcceptableTypeAddrRange {
return nil
}
typeAddr = &TypeAddr{
BaseTypeAddr: min,
MaxTypeAddr: max,
AddrRange: addrRange,
AddrShift: addrShift,
}
return typeAddr
}

0 comments on commit 7e03a13

Please sign in to comment.