diff options
| author | Lorenz Bauer <oss@lmb.io> | 2024-05-16 11:22:36 +0100 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-05-20 19:16:18 +0000 |
| commit | 447ad32a1db8492ce8549ae27e0b72b611938253 (patch) | |
| tree | bb1628bded4f12ec83bf97829e2c1605666145b1 /src/encoding/binary/binary.go | |
| parent | 04bf36e97305197d09554739391f607afde1fd74 (diff) | |
| download | go-447ad32a1db8492ce8549ae27e0b72b611938253.tar.xz | |
encoding/binary: speed up Size
Size() is currently not called from the fast path, since the package
handles the buffer sizing for Read and Write internally. This will change
when adding Append() because callers can use Size to avoid allocations when
writing into bytes.Buffer via AvailableBuffer for example.
Add a fast path for simple types and extend the existing struct size cache
to arrays of structs.
Change-Id: I3af16a2b6c9e2dbe6166a2f8c96bcd2e936719e2
Reviewed-on: https://go-review.googlesource.com/c/go/+/584358
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Austin Clements <austin@google.com>
Diffstat (limited to 'src/encoding/binary/binary.go')
| -rw-r--r-- | src/encoding/binary/binary.go | 93 |
1 files changed, 92 insertions, 1 deletions
diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go index 55aa880ea5..6056b8dd99 100644 --- a/src/encoding/binary/binary.go +++ b/src/encoding/binary/binary.go @@ -579,6 +579,97 @@ func encodeFast(bs []byte, order ByteOrder, data any) { // must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. // If v is neither of these, Size returns -1. func Size(v any) int { + switch data := v.(type) { + case bool, int8, uint8: + return 1 + case *bool: + if data == nil { + return -1 + } + return 1 + case *int8: + if data == nil { + return -1 + } + return 1 + case *uint8: + if data == nil { + return -1 + } + return 1 + case []bool: + return len(data) + case []int8: + return len(data) + case []uint8: + return len(data) + case int16, uint16: + return 2 + case *int16: + if data == nil { + return -1 + } + return 2 + case *uint16: + if data == nil { + return -1 + } + return 2 + case []int16: + return 2 * len(data) + case []uint16: + return 2 * len(data) + case int32, uint32: + return 4 + case *int32: + if data == nil { + return -1 + } + return 4 + case *uint32: + if data == nil { + return -1 + } + return 4 + case []int32: + return 4 * len(data) + case []uint32: + return 4 * len(data) + case int64, uint64: + return 8 + case *int64: + if data == nil { + return -1 + } + return 8 + case *uint64: + if data == nil { + return -1 + } + return 8 + case []int64: + return 8 * len(data) + case []uint64: + return 8 * len(data) + case float32: + return 4 + case *float32: + if data == nil { + return -1 + } + return 4 + case float64: + return 8 + case *float64: + if data == nil { + return -1 + } + return 8 + case []float32: + return 4 * len(data) + case []float64: + return 8 * len(data) + } return dataSize(reflect.Indirect(reflect.ValueOf(v))) } @@ -590,7 +681,7 @@ var structSize sync.Map // map[reflect.Type]int // occupied by the header. If the type of v is not acceptable, dataSize returns -1. func dataSize(v reflect.Value) int { switch v.Kind() { - case reflect.Slice: + case reflect.Slice, reflect.Array: t := v.Type().Elem() if size, ok := structSize.Load(t); ok { return size.(int) * v.Len() |
