Optimize decoding of struct field

This commit is contained in:
Masaaki Goshima 2021-02-11 22:10:14 +09:00
parent 5daa24c97c
commit f8c7c7a612
1 changed files with 7 additions and 86 deletions

View File

@ -109,8 +109,13 @@ func (d *structDecoder) tryOptimize() {
sortedKeys = append(sortedKeys, key) sortedKeys = append(sortedKeys, key)
} }
sort.Strings(sortedKeys) sort.Strings(sortedKeys)
// By allocating one extra capacity than `maxKeyLen`,
// it is possible to avoid the process of comparing the index of the key with the length of the bitmap each time.
bitmapLen := maxKeyLen + 1
if len(sortedKeys) <= 8 { if len(sortedKeys) <= 8 {
keyBitmap := make([][256]int8, maxKeyLen) // maxKeyLen
keyBitmap := make([][256]int8, bitmapLen)
for i, key := range sortedKeys { for i, key := range sortedKeys {
for j := 0; j < len(key); j++ { for j := 0; j < len(key); j++ {
c := key[j] c := key[j]
@ -122,7 +127,7 @@ func (d *structDecoder) tryOptimize() {
d.keyDecoder = decodeKeyByBitmapInt8 d.keyDecoder = decodeKeyByBitmapInt8
d.keyStreamDecoder = decodeKeyByBitmapInt8Stream d.keyStreamDecoder = decodeKeyByBitmapInt8Stream
} else { } else {
keyBitmap := make([][256]int16, maxKeyLen) keyBitmap := make([][256]int16, bitmapLen)
for i, key := range sortedKeys { for i, key := range sortedKeys {
for j := 0; j < len(key); j++ { for j := 0; j < len(key); j++ {
c := key[j] c := key[j]
@ -158,7 +163,6 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt8 bitmap := d.keyBitmapInt8
keyBitmapLen := len(bitmap)
start := cursor start := cursor
for { for {
c := char(b, cursor) c := char(b, cursor)
@ -177,23 +181,6 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
case nul: case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
default: default:
if keyIdx >= keyBitmapLen {
for {
cursor++
switch char(b, cursor) {
case '"':
cursor++
return cursor, field, nil
case '\\':
cursor++
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
}
}
curBit &= bitmap[keyIdx][largeToSmallTable[c]] curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 { if curBit == 0 {
for { for {
@ -244,7 +231,6 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt16 bitmap := d.keyBitmapInt16
keyBitmapLen := len(bitmap)
start := cursor start := cursor
for { for {
c := char(b, cursor) c := char(b, cursor)
@ -263,23 +249,6 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
case nul: case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
default: default:
if keyIdx >= keyBitmapLen {
for {
cursor++
switch char(b, cursor) {
case '"':
cursor++
return cursor, field, nil
case '\\':
cursor++
if char(b, cursor) == nul {
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
case nul:
return 0, nil, errUnexpectedEndOfJSON("string", cursor)
}
}
}
curBit &= bitmap[keyIdx][largeToSmallTable[c]] curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 { if curBit == 0 {
for { for {
@ -352,7 +321,6 @@ func decodeKeyByBitmapInt8Stream(d *structDecoder, s *stream) (*structFieldSet,
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt8 bitmap := d.keyBitmapInt8
keyBitmapLen := len(bitmap)
for { for {
c := s.char() c := s.char()
switch c { switch c {
@ -373,29 +341,6 @@ func decodeKeyByBitmapInt8Stream(d *structDecoder, s *stream) (*structFieldSet,
} }
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
default: default:
if keyIdx >= keyBitmapLen {
for {
s.cursor++
switch s.char() {
case '"':
b := s.buf[start:s.cursor]
key := *(*string)(unsafe.Pointer(&b))
s.cursor++
return field, key, nil
case '\\':
s.cursor++
if s.char() == nul {
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
}
}
case nul:
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
}
}
}
}
curBit &= bitmap[keyIdx][largeToSmallTable[c]] curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 { if curBit == 0 {
for { for {
@ -460,7 +405,6 @@ func decodeKeyByBitmapInt16Stream(d *structDecoder, s *stream) (*structFieldSet,
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt16 bitmap := d.keyBitmapInt16
keyBitmapLen := len(bitmap)
for { for {
c := s.char() c := s.char()
switch c { switch c {
@ -481,29 +425,6 @@ func decodeKeyByBitmapInt16Stream(d *structDecoder, s *stream) (*structFieldSet,
} }
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
default: default:
if keyIdx >= keyBitmapLen {
for {
s.cursor++
switch s.char() {
case '"':
b := s.buf[start:s.cursor]
key := *(*string)(unsafe.Pointer(&b))
s.cursor++
return field, key, nil
case '\\':
s.cursor++
if s.char() == nul {
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
}
}
case nul:
if !s.read() {
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
}
}
}
}
curBit &= bitmap[keyIdx][largeToSmallTable[c]] curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 { if curBit == 0 {
for { for {