From 22fff1b9abc943b4123732940a0e05960d45fb5b455d3133c379538cc5578647 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 12 Dec 2024 12:40:33 +0300 Subject: [PATCH] Less pointers Item, Raw, Blob are rather small structures, so an additional pointer may hurt performance. --- gyac/atom/dec.go | 2 +- gyac/atom/enc.go | 2 +- gyac/blob.go | 6 +-- gyac/cmd/test-vector-anys/main.go | 6 +-- gyac/cmd/test-vector-manual/main.go | 6 +-- gyac/dec.go | 15 +++--- gyac/enc.go | 10 ++-- gyac/fromgo.go | 72 +++++++++++++++-------------- gyac/fuzz_test.go | 2 +- gyac/mapstruct/dec.go | 2 +- gyac/togo.go | 16 +++---- gyac/yacpki/signed-data.go | 4 +- 12 files changed, 73 insertions(+), 70 deletions(-) diff --git a/gyac/atom/dec.go b/gyac/atom/dec.go index 653bcb4..6fccb3f 100644 --- a/gyac/atom/dec.go +++ b/gyac/atom/dec.go @@ -225,7 +225,7 @@ func Decode(buf []byte) (t types.Type, v any, off int, err error) { return } t = types.Raw - v = &Raw{T: Type(tag), V: buf[1 : 1+l]} + v = Raw{T: Type(tag), V: buf[1 : 1+l]} case TAI64, TAI64N, TAI64NA: var l int diff --git a/gyac/atom/enc.go b/gyac/atom/enc.go index df9ceee..39c4af0 100644 --- a/gyac/atom/enc.go +++ b/gyac/atom/enc.go @@ -173,6 +173,6 @@ func TAI64Encode(buf, tai []byte) []byte { } } -func RawEncode(buf []byte, raw *Raw) []byte { +func RawEncode(buf []byte, raw Raw) []byte { return append(append(buf, byte(raw.T)), raw.V...) } diff --git a/gyac/blob.go b/gyac/blob.go index dc50290..1566e21 100644 --- a/gyac/blob.go +++ b/gyac/blob.go @@ -30,8 +30,8 @@ func (blob *Blob) String() string { return fmt.Sprintf("BLOB(%d, %d)", blob.ChunkLen, l) } -func MakeBlob(chunkLen int, data []byte) *Blob { - blob := Blob{ChunkLen: chunkLen} +func MakeBlob(chunkLen int, data []byte) (blob Blob) { + blob.ChunkLen = chunkLen n := len(data) / chunkLen for i := 0; i < n; i++ { blob.Chunks = append(blob.Chunks, data[i*chunkLen:(i+1)*chunkLen]) @@ -40,5 +40,5 @@ func MakeBlob(chunkLen int, data []byte) *Blob { if left > 0 { blob.Chunks = append(blob.Chunks, data[len(data)-left:]) } - return &blob + return } diff --git a/gyac/cmd/test-vector-anys/main.go b/gyac/cmd/test-vector-anys/main.go index 2e5d03d..ae4bad7 100644 --- a/gyac/cmd/test-vector-anys/main.go +++ b/gyac/cmd/test-vector-anys/main.go @@ -87,7 +87,7 @@ func main() { map[string]any{}, gyac.MakeBlob(123, []byte{}), uuid.Nil, - &atom.Raw{ + atom.Raw{ T: atom.TAI64, V: []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), }, @@ -96,13 +96,13 @@ func main() { time.Unix(1234567890, 0), time.Unix(1234567890, 456*1000), time.Unix(1234567890, 456789), - &atom.Raw{ + atom.Raw{ T: atom.TAI64NA, V: []byte("\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55\x07\x5B\xCD\x15"), }, }, "floats": []any{ - &atom.Raw{T: atom.Float32, V: []byte("\x01\x02\x03\x04")}, + atom.Raw{T: atom.Float32, V: []byte("\x01\x02\x03\x04")}, }, "uuid": uuid.MustParse("0e875e3f-d385-49eb-87b4-be42d641c367"), } diff --git a/gyac/cmd/test-vector-manual/main.go b/gyac/cmd/test-vector-manual/main.go index d9fdbb2..c34e17e 100644 --- a/gyac/cmd/test-vector-manual/main.go +++ b/gyac/cmd/test-vector-manual/main.go @@ -158,7 +158,7 @@ func main() { tai.FromTime(t) buf = atom.TAI64Encode(buf, tai[:]) } - buf = atom.RawEncode(buf, &atom.Raw{ + buf = atom.RawEncode(buf, atom.Raw{ T: atom.TAI64NA, V: []byte("\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55\x07\x5B\xCD\x15"), }) @@ -167,7 +167,7 @@ func main() { { buf = atom.StrEncode(buf, "floats") buf = atom.ListEncode(buf) - buf = atom.RawEncode(buf, &atom.Raw{ + buf = atom.RawEncode(buf, atom.Raw{ T: atom.Float32, V: []byte("\x01\x02\x03\x04"), }) @@ -189,7 +189,7 @@ func main() { buf = atom.BinEncode(buf, []byte{}) } buf = atom.UUIDEncode(buf, uuid.Nil) - buf = atom.RawEncode(buf, &atom.Raw{ + buf = atom.RawEncode(buf, atom.Raw{ T: atom.TAI64, V: []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), }) diff --git a/gyac/dec.go b/gyac/dec.go index 244e524..a3561d8 100644 --- a/gyac/dec.go +++ b/gyac/dec.go @@ -41,13 +41,12 @@ func decode( buf []byte, allowContainers, expectEOC bool, recursionDepth int, -) (item *Item, tail []byte, err error) { +) (item Item, tail []byte, err error) { if recursionDepth > ParseMaxRecursionDepth { err = errors.New("deep recursion") return } var off int - item = &Item{} item.T, item.V, off, err = atom.Decode(buf) if err != nil { return @@ -65,8 +64,8 @@ func decode( err = atom.ErrUnknownType return } - var sub *Item - var v []*Item + var sub Item + var v []Item for { sub, buf, err = decode(buf, true, true, recursionDepth+1) tail = buf @@ -86,8 +85,8 @@ func decode( err = atom.ErrUnknownType return } - v := make(map[string]*Item) - var sub *Item + v := make(map[string]Item) + var sub Item var keyPrev string for { sub, buf, err = decode(buf, false, true, recursionDepth+1) @@ -132,8 +131,8 @@ func decode( return } chunkLen := int(item.V.(uint64)) - v := &Blob{ChunkLen: chunkLen} - var sub *Item + v := Blob{ChunkLen: chunkLen} + var sub Item BlobCycle: for { sub, buf, err = decode(buf, false, true, recursionDepth+1) diff --git a/gyac/enc.go b/gyac/enc.go index 756ec97..92de56a 100644 --- a/gyac/enc.go +++ b/gyac/enc.go @@ -25,7 +25,7 @@ import ( "go.cypherpunks.su/yac/gyac/types" ) -func (item *Item) Encode(buf []byte) []byte { +func (item Item) Encode(buf []byte) []byte { switch item.T { case types.NIL: return atom.NILEncode(buf) @@ -41,12 +41,12 @@ func (item *Item) Encode(buf []byte) []byte { return atom.BigIntEncode(buf, item.V.(*big.Int)) case types.List: buf = atom.ListEncode(buf) - for _, v := range item.V.([]*Item) { + for _, v := range item.V.([]Item) { buf = v.Encode(buf) } buf = atom.EOCEncode(buf) case types.Map: - m := item.V.(map[string]*Item) + m := item.V.(map[string]Item) keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) @@ -59,7 +59,7 @@ func (item *Item) Encode(buf []byte) []byte { } buf = atom.EOCEncode(buf) case types.Blob: - blob := item.V.(*Blob) + blob := item.V.(Blob) buf = atom.BlobEncode(buf, blob.ChunkLen) for _, chunk := range blob.Chunks { if len(chunk) == blob.ChunkLen { @@ -83,7 +83,7 @@ func (item *Item) Encode(buf []byte) []byte { case types.Str: return atom.StrEncode(buf, item.V.(string)) case types.Raw: - return atom.RawEncode(buf, item.V.(*atom.Raw)) + return atom.RawEncode(buf, item.V.(atom.Raw)) default: panic("unhandled type") } diff --git a/gyac/fromgo.go b/gyac/fromgo.go index 9b48623..5ea9bae 100644 --- a/gyac/fromgo.go +++ b/gyac/fromgo.go @@ -44,17 +44,19 @@ func structTagRead(f reflect.StructField) (name string, omit bool) { return } -func FromGo(v any) *Item { +func FromGo(v any) Item { if v == nil { - return &Item{T: types.NIL} + return Item{T: types.NIL} } rv := reflect.ValueOf(v) if b, ok := v.([]byte); ok { - return &Item{T: types.Bin, V: b} + return Item{T: types.Bin, V: b} } switch v := v.(type) { case *Blob: - return &Item{T: types.Blob, V: v} + return Item{T: types.Blob, V: *v} + case Blob: + return Item{T: types.Blob, V: v} case time.Time: t := tai64n.Leapsecs.Add(v) var taiRaw []byte @@ -67,20 +69,22 @@ func FromGo(v any) *Item { tai.FromTime(t) taiRaw = tai[:] } - return &Item{T: types.TAI64, V: taiRaw} + return Item{T: types.TAI64, V: taiRaw} case *atom.Raw: - return &Item{T: types.Raw, V: v} + return Item{T: types.Raw, V: *v} + case atom.Raw: + return Item{T: types.Raw, V: v} case *big.Int: - return &Item{T: types.BigInt, V: v} + return Item{T: types.BigInt, V: v} } switch reflect.TypeOf(v).Kind() { case reflect.Pointer: if rv.IsNil() { - return &Item{T: types.NIL} + return Item{T: types.NIL} } return FromGo(rv.Elem().Interface()) case reflect.Slice: - var ret []*Item + var ret []Item if anys, ok := v.([]any); ok { for _, v := range anys { ret = append(ret, FromGo(v)) @@ -91,19 +95,19 @@ func FromGo(v any) *Item { ret = append(ret, FromGo(rv.Index(i).Interface())) } } - return &Item{T: types.List, V: ret} + return Item{T: types.List, V: ret} case reflect.Map: - ret := make(map[string]*Item, rv.Len()) + ret := make(map[string]Item, rv.Len()) iter := rv.MapRange() for iter.Next() { ret[iter.Key().String()] = FromGo(iter.Value().Interface()) } - return &Item{T: types.Map, V: ret} + return Item{T: types.Map, V: ret} } { t := rv.Type() if t.Kind() == reflect.Struct { - ret := make(map[string]*Item) + ret := make(map[string]Item) for _, f := range reflect.VisibleFields(t) { fv := rv.FieldByIndex(f.Index) name, omit := structTagRead(f) @@ -113,11 +117,11 @@ func FromGo(v any) *Item { case types.NIL: empty = true case types.List: - if len(item.V.([]*Item)) == 0 { + if len(item.V.([]Item)) == 0 { empty = true } case types.Map: - if len(item.V.(map[string]*Item)) == 0 { + if len(item.V.(map[string]Item)) == 0 { empty = true } } @@ -125,51 +129,51 @@ func FromGo(v any) *Item { ret[name] = item } } - return &Item{T: types.Map, V: ret} + return Item{T: types.Map, V: ret} } } switch v := v.(type) { case bool: - return &Item{T: types.Bool, V: v} + return Item{T: types.Bool, V: v} case uuid.UUID: - return &Item{T: types.UUID, V: v} + return Item{T: types.UUID, V: v} case uint: - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} case uint8: - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} case uint16: - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} case uint32: - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} case uint64: - return &Item{T: types.UInt, V: v} + return Item{T: types.UInt, V: v} case int: if v >= 0 { - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} } - return &Item{T: types.Int, V: int64(v)} + return Item{T: types.Int, V: int64(v)} case int8: if v >= 0 { - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} } - return &Item{T: types.Int, V: int64(v)} + return Item{T: types.Int, V: int64(v)} case int16: if v >= 0 { - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} } - return &Item{T: types.Int, V: int64(v)} + return Item{T: types.Int, V: int64(v)} case int32: if v >= 0 { - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} } - return &Item{T: types.Int, V: int64(v)} + return Item{T: types.Int, V: int64(v)} case int64: if v >= 0 { - return &Item{T: types.UInt, V: uint64(v)} + return Item{T: types.UInt, V: uint64(v)} } - return &Item{T: types.Int, V: v} + return Item{T: types.Int, V: v} case string: - return &Item{T: types.Str, V: v} + return Item{T: types.Str, V: v} default: panic(fmt.Errorf("unhandled type: %+v", v)) } diff --git a/gyac/fuzz_test.go b/gyac/fuzz_test.go index 795ab88..103e4da 100644 --- a/gyac/fuzz_test.go +++ b/gyac/fuzz_test.go @@ -6,7 +6,7 @@ import ( ) func FuzzItemDecode(f *testing.F) { - var item *Item + var item Item var err error var tail []byte f.Fuzz(func(t *testing.T, b []byte) { diff --git a/gyac/mapstruct/dec.go b/gyac/mapstruct/dec.go index fadf768..bcba9ff 100644 --- a/gyac/mapstruct/dec.go +++ b/gyac/mapstruct/dec.go @@ -23,7 +23,7 @@ import ( ) func Decode(dst any, raw []byte) (tail []byte, err error) { - var item *gyac.Item + var item gyac.Item item, tail, err = gyac.Decode(raw) if err != nil { return diff --git a/gyac/togo.go b/gyac/togo.go index ec10fa7..4dc62f9 100644 --- a/gyac/togo.go +++ b/gyac/togo.go @@ -25,7 +25,7 @@ import ( "go.cypherpunks.su/yac/gyac/types" ) -func (item *Item) ToGo() any { +func (item Item) ToGo() any { switch item.T { case types.NIL: return nil @@ -39,18 +39,18 @@ func (item *Item) ToGo() any { return item.V.(int64) case types.List: var ret []any - for _, v := range item.V.([]*Item) { + for _, v := range item.V.([]Item) { ret = append(ret, v.ToGo()) } return ret case types.Map: ret := make(map[string]any) - for k, v := range item.V.(map[string]*Item) { + for k, v := range item.V.(map[string]Item) { ret[k] = v.ToGo() } return ret case types.Blob: - return item.V.(*Blob) + return item.V.(Blob) case types.BigInt: return item.V.(*big.Int) case types.Float: @@ -62,18 +62,18 @@ func (item *Item) ToGo() any { tai := tai64n.TAI64(raw) t, isLeap := tai64n.Leapsecs.Sub(tai.Time()) if isLeap { - return &atom.Raw{T: atom.TAI64, V: raw} + return atom.Raw{T: atom.TAI64, V: raw} } return t case tai64n.TAI64NSize: tai := tai64n.TAI64N(raw) t, isLeap := tai64n.Leapsecs.Sub(tai.Time()) if isLeap { - return &atom.Raw{T: atom.TAI64N, V: raw} + return atom.Raw{T: atom.TAI64N, V: raw} } return t case tai64n.TAI64NASize: - return &atom.Raw{T: atom.TAI64NA, V: raw} + return atom.Raw{T: atom.TAI64NA, V: raw} default: panic("unexpected TAI size") } @@ -82,7 +82,7 @@ func (item *Item) ToGo() any { case types.Str: return item.V.(string) case types.Raw: - return item.V.(*atom.Raw) + return item.V.(atom.Raw) default: panic(fmt.Errorf("unhandled type: %+v", item)) } diff --git a/gyac/yacpki/signed-data.go b/gyac/yacpki/signed-data.go index 04bc671..1e5bc68 100644 --- a/gyac/yacpki/signed-data.go +++ b/gyac/yacpki/signed-data.go @@ -45,7 +45,7 @@ type SignedData struct { } func SignedDataParse(data []byte) (sd *SignedData, tail []byte, err error) { - var item *gyac.Item + var item gyac.Item item, tail, err = gyac.Decode(data) if err != nil { return @@ -54,7 +54,7 @@ func SignedDataParse(data []byte) (sd *SignedData, tail []byte, err error) { return } -func SignedDataParseItem(item *gyac.Item) (sd *SignedData, err error) { +func SignedDataParseItem(item gyac.Item) (sd *SignedData, err error) { if item.T != types.Map { err = errors.New("SignedDataParse: non-map") return -- 2.50.0