Use bits.TrailingZeros for bitmap field

This commit is contained in:
Masaaki Goshima 2021-02-15 20:05:35 +09:00
parent e080e515fd
commit ddd7019dd3
1 changed files with 27 additions and 36 deletions

View File

@ -3,6 +3,7 @@ package json
import ( import (
"fmt" "fmt"
"math" "math"
"math/bits"
"sort" "sort"
"strings" "strings"
"unsafe" "unsafe"
@ -22,24 +23,18 @@ type structDecoder struct {
structName string structName string
fieldName string fieldName string
isTriedOptimize bool isTriedOptimize bool
keyBitmapInt8 [][256]int8 keyBitmapUint8 [][256]uint8
keyBitmapInt16 [][256]int16 keyBitmapUint16 [][256]uint16
sortedFieldSets []*structFieldSet sortedFieldSets []*structFieldSet
keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error) keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
keyStreamDecoder func(*structDecoder, *stream) (*structFieldSet, string, error) keyStreamDecoder func(*structDecoder, *stream) (*structFieldSet, string, error)
} }
var ( var (
bitHashTable [64]int
largeToSmallTable [256]byte largeToSmallTable [256]byte
) )
func init() { func init() {
hash := uint64(0x03F566ED27179461)
for i := 0; i < 64; i++ {
bitHashTable[hash>>58] = i
hash <<= 1
}
for i := 0; i < 256; i++ { for i := 0; i < 256; i++ {
c := i c := i
if 'A' <= c && c <= 'Z' { if 'A' <= c && c <= 'Z' {
@ -114,7 +109,7 @@ func (d *structDecoder) tryOptimize() {
// it is possible to avoid the process of comparing the index of the key with the length of the bitmap each time. // 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 bitmapLen := maxKeyLen + 1
if len(sortedKeys) <= 8 { if len(sortedKeys) <= 8 {
keyBitmap := make([][256]int8, bitmapLen) keyBitmap := make([][256]uint8, 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,11 +117,11 @@ func (d *structDecoder) tryOptimize() {
} }
d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key]) d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
} }
d.keyBitmapInt8 = keyBitmap d.keyBitmapUint8 = keyBitmap
d.keyDecoder = decodeKeyByBitmapInt8 d.keyDecoder = decodeKeyByBitmapUint8
d.keyStreamDecoder = decodeKeyByBitmapInt8Stream d.keyStreamDecoder = decodeKeyByBitmapUint8Stream
} else { } else {
keyBitmap := make([][256]int16, bitmapLen) keyBitmap := make([][256]uint16, 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]
@ -134,16 +129,16 @@ func (d *structDecoder) tryOptimize() {
} }
d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key]) d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
} }
d.keyBitmapInt16 = keyBitmap d.keyBitmapUint16 = keyBitmap
d.keyDecoder = decodeKeyByBitmapInt16 d.keyDecoder = decodeKeyByBitmapUint16
d.keyStreamDecoder = decodeKeyByBitmapInt16Stream d.keyStreamDecoder = decodeKeyByBitmapUint16Stream
} }
} }
func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
var ( var (
field *structFieldSet field *structFieldSet
curBit int8 = math.MaxInt8 curBit uint8 = math.MaxUint8
) )
b := (*sliceHeader)(unsafe.Pointer(&buf)).data b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for { for {
@ -161,14 +156,13 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt8 bitmap := d.keyBitmapUint8
start := cursor start := cursor
for { for {
c := char(b, cursor) c := char(b, cursor)
switch c { switch c {
case '"': case '"':
x := uint64(curBit & -curBit) fieldSetIndex := bits.TrailingZeros8(curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex] field = d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start keyLen := cursor - start
cursor++ cursor++
@ -208,10 +202,10 @@ func decodeKeyByBitmapInt8(d *structDecoder, buf []byte, cursor int64) (int64, *
} }
} }
func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) { func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
var ( var (
field *structFieldSet field *structFieldSet
curBit int16 = math.MaxInt16 curBit uint16 = math.MaxUint16
) )
b := (*sliceHeader)(unsafe.Pointer(&buf)).data b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for { for {
@ -229,14 +223,13 @@ func decodeKeyByBitmapInt16(d *structDecoder, buf []byte, cursor int64) (int64,
return 0, nil, errUnexpectedEndOfJSON("string", cursor) return 0, nil, errUnexpectedEndOfJSON("string", cursor)
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt16 bitmap := d.keyBitmapUint16
start := cursor start := cursor
for { for {
c := char(b, cursor) c := char(b, cursor)
switch c { switch c {
case '"': case '"':
x := uint64(curBit & -curBit) fieldSetIndex := bits.TrailingZeros16(curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex] field = d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start keyLen := cursor - start
cursor++ cursor++
@ -290,10 +283,10 @@ func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldS
return cursor, field, nil return cursor, field, nil
} }
func decodeKeyByBitmapInt8Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) { func decodeKeyByBitmapUint8Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
var ( var (
field *structFieldSet field *structFieldSet
curBit int8 = math.MaxInt8 curBit uint8 = math.MaxUint8
) )
for { for {
switch s.char() { switch s.char() {
@ -319,13 +312,12 @@ func decodeKeyByBitmapInt8Stream(d *structDecoder, s *stream) (*structFieldSet,
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt8 bitmap := d.keyBitmapUint8
for { for {
c := s.char() c := s.char()
switch c { switch c {
case '"': case '"':
x := uint64(curBit & -curBit) fieldSetIndex := bits.TrailingZeros8(curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex] field = d.sortedFieldSets[fieldSetIndex]
keyLen := s.cursor - start keyLen := s.cursor - start
s.cursor++ s.cursor++
@ -374,10 +366,10 @@ func decodeKeyByBitmapInt8Stream(d *structDecoder, s *stream) (*structFieldSet,
} }
} }
func decodeKeyByBitmapInt16Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) { func decodeKeyByBitmapUint16Stream(d *structDecoder, s *stream) (*structFieldSet, string, error) {
var ( var (
field *structFieldSet field *structFieldSet
curBit int16 = math.MaxInt16 curBit uint16 = math.MaxUint16
) )
for { for {
switch s.char() { switch s.char() {
@ -403,13 +395,12 @@ func decodeKeyByBitmapInt16Stream(d *structDecoder, s *stream) (*structFieldSet,
return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset()) return nil, "", errUnexpectedEndOfJSON("string", s.totalOffset())
} }
keyIdx := 0 keyIdx := 0
bitmap := d.keyBitmapInt16 bitmap := d.keyBitmapUint16
for { for {
c := s.char() c := s.char()
switch c { switch c {
case '"': case '"':
x := uint64(curBit & -curBit) fieldSetIndex := bits.TrailingZeros16(curBit)
fieldSetIndex := bitHashTable[(x*0x03F566ED27179461)>>58]
field = d.sortedFieldSets[fieldSetIndex] field = d.sortedFieldSets[fieldSetIndex]
keyLen := s.cursor - start keyLen := s.cursor - start
s.cursor++ s.cursor++