From 1a5bcd64ec8a5feefa7e3adb76a750633600cecc Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Mon, 11 Jan 2021 21:14:39 +0900 Subject: [PATCH 1/6] msgpack: sort formats struct to msgpack code order Signed-off-by: Koichi Shiraishi --- msgpack/unpack.go | 122 +++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/msgpack/unpack.go b/msgpack/unpack.go index 2663b1bc..d3d7b5b6 100644 --- a/msgpack/unpack.go +++ b/msgpack/unpack.go @@ -263,14 +263,16 @@ var formats = [256]*struct { n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - uint64(fixStringCodeMin), nil }, more: true, }, - negFixIntCodeMin: { - t: Int, - n: func(d *Decoder, code byte) (uint64, error) { return uint64(int64(int8(code))), nil }, - }, nilCode: { t: Nil, n: func(d *Decoder, code byte) (uint64, error) { return 0, nil }, }, + unusedCode: { + t: Invalid, + n: func(d *Decoder, code byte) (uint64, error) { + return 0, fmt.Errorf("msgpack: unknown format code %x", code) + }, + }, falseCode: { t: Bool, n: func(d *Decoder, code byte) (uint64, error) { return 0, nil }, @@ -279,6 +281,36 @@ var formats = [256]*struct { t: Bool, n: func(d *Decoder, code byte) (uint64, error) { return 1, nil }, }, + binary8Code: { + t: Binary, + n: (*Decoder).read1, + more: true, + }, + binary16Code: { + t: Binary, + n: (*Decoder).read2, + more: true, + }, + binary32Code: { + t: Binary, + n: (*Decoder).read4, + more: true, + }, + ext8Code: { + t: Extension, + n: (*Decoder).read1, + more: true, + }, + ext16Code: { + t: Extension, + n: (*Decoder).read2, + more: true, + }, + ext32Code: { + t: Extension, + n: (*Decoder).read4, + more: true, + }, float32Code: { t: Float, n: func(d *Decoder, code byte) (uint64, error) { @@ -331,52 +363,6 @@ var formats = [256]*struct { t: Int, n: (*Decoder).read8, }, - string8Code: { - t: String, - n: (*Decoder).read1, - more: true, - }, - string16Code: { - t: String, - n: (*Decoder).read2, - more: true, - }, - string32Code: { - t: String, - n: (*Decoder).read4, - more: true, - }, - binary8Code: { - t: Binary, - n: (*Decoder).read1, - more: true, - }, - binary16Code: { - t: Binary, - n: (*Decoder).read2, - more: true, - }, - binary32Code: { - t: Binary, - n: (*Decoder).read4, - more: true, - }, - array16Code: { - t: ArrayLen, - n: (*Decoder).read2, - }, - array32Code: { - t: ArrayLen, - n: (*Decoder).read4, - }, - map16Code: { - t: MapLen, - n: (*Decoder).read2, - }, - map32Code: { - t: MapLen, - n: (*Decoder).read4, - }, fixExt1Code: { t: Extension, n: func(d *Decoder, code byte) (uint64, error) { return 1, nil }, @@ -402,26 +388,40 @@ var formats = [256]*struct { n: func(d *Decoder, code byte) (uint64, error) { return 16, nil }, more: true, }, - ext8Code: { - t: Extension, + string8Code: { + t: String, n: (*Decoder).read1, more: true, }, - ext16Code: { - t: Extension, + string16Code: { + t: String, n: (*Decoder).read2, more: true, }, - ext32Code: { - t: Extension, + string32Code: { + t: String, n: (*Decoder).read4, more: true, }, - unusedCode: { - t: Invalid, - n: func(d *Decoder, code byte) (uint64, error) { - return 0, fmt.Errorf("msgpack: unknown format code %x", code) - }, + array16Code: { + t: ArrayLen, + n: (*Decoder).read2, + }, + array32Code: { + t: ArrayLen, + n: (*Decoder).read4, + }, + map16Code: { + t: MapLen, + n: (*Decoder).read2, + }, + map32Code: { + t: MapLen, + n: (*Decoder).read4, + }, + negFixIntCodeMin: { + t: Int, + n: func(d *Decoder, code byte) (uint64, error) { return uint64(int64(int8(code))), nil }, }, } From 270e5a4e8164fe6d7a0255f1bd06097928e988bc Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Mon, 11 Jan 2021 21:15:30 +0900 Subject: [PATCH 2/6] msgpack: rename formats n field to fn Signed-off-by: Koichi Shiraishi --- msgpack/unpack.go | 112 +++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/msgpack/unpack.go b/msgpack/unpack.go index d3d7b5b6..03fc901b 100644 --- a/msgpack/unpack.go +++ b/msgpack/unpack.go @@ -172,7 +172,7 @@ func (d *Decoder) Unpack() error { f := formats[code] d.t = f.t - d.n, err = f.n(d, code) + d.n, err = f.fn(d, code) if err != nil { return d.fatal(err) } @@ -243,185 +243,185 @@ func (d *Decoder) skipCount() int { var formats = [256]*struct { t Type - n func(d *Decoder, code byte) (uint64, error) + fn func(d *Decoder, code byte) (uint64, error) more bool }{ fixIntCodeMin: { - t: Int, - n: func(d *Decoder, code byte) (uint64, error) { return uint64(code), nil }, + t: Int, + fn: func(d *Decoder, code byte) (uint64, error) { return uint64(code), nil }, }, fixMapCodeMin: { - t: MapLen, - n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - uint64(fixMapCodeMin), nil }, + t: MapLen, + fn: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - uint64(fixMapCodeMin), nil }, }, fixArrayCodeMin: { - t: ArrayLen, - n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - uint64(fixArrayCodeMin), nil }, + t: ArrayLen, + fn: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - uint64(fixArrayCodeMin), nil }, }, fixStringCodeMin: { t: String, - n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - uint64(fixStringCodeMin), nil }, + fn: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - uint64(fixStringCodeMin), nil }, more: true, }, nilCode: { - t: Nil, - n: func(d *Decoder, code byte) (uint64, error) { return 0, nil }, + t: Nil, + fn: func(d *Decoder, code byte) (uint64, error) { return 0, nil }, }, unusedCode: { t: Invalid, - n: func(d *Decoder, code byte) (uint64, error) { + fn: func(d *Decoder, code byte) (uint64, error) { return 0, fmt.Errorf("msgpack: unknown format code %x", code) }, }, falseCode: { - t: Bool, - n: func(d *Decoder, code byte) (uint64, error) { return 0, nil }, + t: Bool, + fn: func(d *Decoder, code byte) (uint64, error) { return 0, nil }, }, trueCode: { - t: Bool, - n: func(d *Decoder, code byte) (uint64, error) { return 1, nil }, + t: Bool, + fn: func(d *Decoder, code byte) (uint64, error) { return 1, nil }, }, binary8Code: { t: Binary, - n: (*Decoder).read1, + fn: (*Decoder).read1, more: true, }, binary16Code: { t: Binary, - n: (*Decoder).read2, + fn: (*Decoder).read2, more: true, }, binary32Code: { t: Binary, - n: (*Decoder).read4, + fn: (*Decoder).read4, more: true, }, ext8Code: { t: Extension, - n: (*Decoder).read1, + fn: (*Decoder).read1, more: true, }, ext16Code: { t: Extension, - n: (*Decoder).read2, + fn: (*Decoder).read2, more: true, }, ext32Code: { t: Extension, - n: (*Decoder).read4, + fn: (*Decoder).read4, more: true, }, float32Code: { t: Float, - n: func(d *Decoder, code byte) (uint64, error) { + fn: func(d *Decoder, code byte) (uint64, error) { n, err := d.read4(code) return math.Float64bits(float64(math.Float32frombits(uint32(n)))), err }, }, float64Code: { - t: Float, - n: (*Decoder).read8, + t: Float, + fn: (*Decoder).read8, }, uint8Code: { - t: Uint, - n: (*Decoder).read1, + t: Uint, + fn: (*Decoder).read1, }, uint16Code: { - t: Uint, - n: (*Decoder).read2, + t: Uint, + fn: (*Decoder).read2, }, uint32Code: { - t: Uint, - n: (*Decoder).read4, + t: Uint, + fn: (*Decoder).read4, }, uint64Code: { - t: Uint, - n: (*Decoder).read8, + t: Uint, + fn: (*Decoder).read8, }, int8Code: { t: Int, - n: func(d *Decoder, code byte) (uint64, error) { + fn: func(d *Decoder, code byte) (uint64, error) { n, err := d.read1(code) return uint64(int64(int8(n))), err }, }, int16Code: { t: Int, - n: func(d *Decoder, code byte) (uint64, error) { + fn: func(d *Decoder, code byte) (uint64, error) { n, err := d.read2(code) return uint64(int64(int16(n))), err }, }, int32Code: { t: Int, - n: func(d *Decoder, code byte) (uint64, error) { + fn: func(d *Decoder, code byte) (uint64, error) { n, err := d.read4(code) return uint64(int64(int32(n))), err }, }, int64Code: { - t: Int, - n: (*Decoder).read8, + t: Int, + fn: (*Decoder).read8, }, fixExt1Code: { t: Extension, - n: func(d *Decoder, code byte) (uint64, error) { return 1, nil }, + fn: func(d *Decoder, code byte) (uint64, error) { return 1, nil }, more: true, }, fixExt2Code: { t: Extension, - n: func(d *Decoder, code byte) (uint64, error) { return 2, nil }, + fn: func(d *Decoder, code byte) (uint64, error) { return 2, nil }, more: true, }, fixExt4Code: { t: Extension, - n: func(d *Decoder, code byte) (uint64, error) { return 4, nil }, + fn: func(d *Decoder, code byte) (uint64, error) { return 4, nil }, more: true, }, fixExt8Code: { t: Extension, - n: func(d *Decoder, code byte) (uint64, error) { return 8, nil }, + fn: func(d *Decoder, code byte) (uint64, error) { return 8, nil }, more: true, }, fixExt16Code: { t: Extension, - n: func(d *Decoder, code byte) (uint64, error) { return 16, nil }, + fn: func(d *Decoder, code byte) (uint64, error) { return 16, nil }, more: true, }, string8Code: { t: String, - n: (*Decoder).read1, + fn: (*Decoder).read1, more: true, }, string16Code: { t: String, - n: (*Decoder).read2, + fn: (*Decoder).read2, more: true, }, string32Code: { t: String, - n: (*Decoder).read4, + fn: (*Decoder).read4, more: true, }, array16Code: { - t: ArrayLen, - n: (*Decoder).read2, + t: ArrayLen, + fn: (*Decoder).read2, }, array32Code: { - t: ArrayLen, - n: (*Decoder).read4, + t: ArrayLen, + fn: (*Decoder).read4, }, map16Code: { - t: MapLen, - n: (*Decoder).read2, + t: MapLen, + fn: (*Decoder).read2, }, map32Code: { - t: MapLen, - n: (*Decoder).read4, + t: MapLen, + fn: (*Decoder).read4, }, negFixIntCodeMin: { - t: Int, - n: func(d *Decoder, code byte) (uint64, error) { return uint64(int64(int8(code))), nil }, + t: Int, + fn: func(d *Decoder, code byte) (uint64, error) { return uint64(int64(int8(code))), nil }, }, } From 08cb85b3196e82b8a5d5e5b2543703d77669a184 Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Mon, 11 Jan 2021 21:16:27 +0900 Subject: [PATCH 3/6] msgpack: remove unused format arg name Signed-off-by: Koichi Shiraishi --- msgpack/unpack.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/msgpack/unpack.go b/msgpack/unpack.go index 03fc901b..ddffdb90 100644 --- a/msgpack/unpack.go +++ b/msgpack/unpack.go @@ -457,13 +457,13 @@ func (d *Decoder) fatal(err error) error { return err } -func (d *Decoder) read1(format byte) (uint64, error) { +func (d *Decoder) read1(byte) (uint64, error) { b, err := d.r.ReadByte() return uint64(b), err } -func (d *Decoder) read2(format byte) (uint64, error) { +func (d *Decoder) read2(byte) (uint64, error) { p, err := d.r.Peek(2) if err != nil { return 0, err @@ -473,7 +473,7 @@ func (d *Decoder) read2(format byte) (uint64, error) { return uint64(p[1]) | uint64(p[0])<<8, nil } -func (d *Decoder) read4(format byte) (uint64, error) { +func (d *Decoder) read4(byte) (uint64, error) { p, err := d.r.Peek(4) if err != nil { return 0, err @@ -483,7 +483,7 @@ func (d *Decoder) read4(format byte) (uint64, error) { return uint64(p[3]) | uint64(p[2])<<8 | uint64(p[1])<<16 | uint64(p[0])<<24, nil } -func (d *Decoder) read8(format byte) (uint64, error) { +func (d *Decoder) read8(byte) (uint64, error) { p, err := d.r.Peek(8) if err != nil { return 0, err From c229f6caeb64f905060be6e9bd02c4ae8748a777 Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Tue, 12 Jan 2021 05:03:35 +0900 Subject: [PATCH 4/6] msgpack: sort type and function Signed-off-by: Koichi Shiraishi --- msgpack/unpack.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/msgpack/unpack.go b/msgpack/unpack.go index ddffdb90..65c2e120 100644 --- a/msgpack/unpack.go +++ b/msgpack/unpack.go @@ -57,6 +57,13 @@ func (t Type) String() string { // ErrDataSizeTooLarge is the data size too large error. var ErrDataSizeTooLarge = errors.New("msgpack: data size too large") +// ExtensionMap specifies functions for converting MessagePack extensions to Go +// values. +// +// The key is the MessagePack extension type. +// The value is a function that converts the extension data to a Go value. +type ExtensionMap map[int]func([]byte) (interface{}, error) + // Decoder reads MessagePack objects from an io.Reader. type Decoder struct { extensions ExtensionMap @@ -77,13 +84,6 @@ func NewDecoder(r io.Reader) *Decoder { } } -// ExtensionMap specifies functions for converting MessagePack extensions to Go -// values. -// -// The key is the MessagePack extension type. -// The value is a function that converts the extension data to a Go value. -type ExtensionMap map[int]func([]byte) (interface{}, error) - // SetExtensions specifies functions for converting MessagePack extensions to Go // values. func (d *Decoder) SetExtensions(extensions ExtensionMap) { From 7e7bcb680061d489e60d158ffbc5e5ad151a4b73 Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Tue, 12 Jan 2021 05:06:18 +0900 Subject: [PATCH 5/6] msgpack: split type switch case to reflect.Int specific case Signed-off-by: Koichi Shiraishi --- msgpack/field.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/msgpack/field.go b/msgpack/field.go index de39ddb7..de7abc7f 100644 --- a/msgpack/field.go +++ b/msgpack/field.go @@ -101,12 +101,16 @@ func collectFields(fields []*field, t reflect.Type, visited map[reflect.Type]boo // Parse empty field tag if e := sf.Tag.Get("empty"); e != "" { switch sf.Type.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - bits := 0 - if sf.Type.Kind() != reflect.Int { - bits = sf.Type.Bits() + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + v, err := strconv.ParseInt(e, 10, sf.Type.Bits()) + if err != nil { + panic(fmt.Errorf("msgpack: error parsing field empty field %s.%s: %w", t.Name(), sf.Name, err)) } - v, err := strconv.ParseInt(e, 10, bits) + f.empty = reflect.New(sf.Type).Elem() + f.empty.SetInt(v) + + case reflect.Int: + v, err := strconv.ParseInt(e, 10, 0) if err != nil { panic(fmt.Errorf("msgpack: error parsing field empty field %s.%s: %w", t.Name(), sf.Name, err)) } From 2732b5d58f09a87c89084d5f12ab3469d9cb28d9 Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Sun, 28 Nov 2021 06:20:34 +0900 Subject: [PATCH 6/6] msgpack: add bounds check hint to compiler to fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta _correctFilels/Named-20 9.55µs ± 0% 9.45µs ± 1% -1.02% (p=0.008 n=5+5) _correctFilels/Empty-20 9.60µs ± 0% 9.88µs ±10% ~ (p=1.000 n=5+5) _correctFilels/OmitEmpty-20 10.9µs ± 1% 11.2µs ± 6% ~ (p=0.095 n=5+5) [Geo mean] 10.0µs 10.1µs +1.38% name old alloc/op new alloc/op delta _correctFilels/Named-20 4.75kB ± 0% 4.75kB ± 0% ~ (all equal) _correctFilels/Empty-20 4.75kB ± 0% 4.75kB ± 0% ~ (p=0.333 n=5+4) _correctFilels/OmitEmpty-20 5.10kB ± 0% 5.10kB ± 0% ~ (all equal) [Geo mean] 4.86kB 4.86kB -0.00% name old allocs/op new allocs/op delta _correctFilels/Named-20 96.0 ± 0% 96.0 ± 0% ~ (all equal) _correctFilels/Empty-20 96.0 ± 0% 96.0 ± 0% ~ (all equal) _correctFilels/OmitEmpty-20 96.0 ± 0% 96.0 ± 0% ~ (all equal) [Geo mean] 96.0 96.0 +0.00% Signed-off-by: Koichi Shiraishi --- msgpack/field.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/msgpack/field.go b/msgpack/field.go index de7abc7f..69c3bbb0 100644 --- a/msgpack/field.go +++ b/msgpack/field.go @@ -74,6 +74,8 @@ func collectFields(fields []*field, t reflect.Type, visited map[reflect.Type]boo } if len(index) == d { + _ = fields[len(fields)-1] // bounds check hint to compiler + // There is another field with same name and same depth // Remove that field and skip this field j := 0