From 79a6817d7023bf5ede6db8fee16994afe3e32025 Mon Sep 17 00:00:00 2001 From: Alun Evans Date: Thu, 30 Nov 2023 16:11:21 -0800 Subject: [PATCH] Switch to Append style encoding Signed-off-by: Alun Evans --- marshalers.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/marshalers.go b/marshalers.go index ba1aee509..db89a8b60 100644 --- a/marshalers.go +++ b/marshalers.go @@ -10,6 +10,7 @@ import ( "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/sys" "github.com/cilium/ebpf/internal/sysenc" + "golang.org/x/exp/slices" ) // marshalMapSyscallInput converts an arbitrary value into a pointer suitable @@ -43,33 +44,36 @@ func makeMapSyscallOutput(dst any, length int) sysenc.Buffer { return sysenc.SyscallOutput(dst, length) } -// marshalSlice encodes a slice containing one value per +// appendPerCPUSlice encodes a slice containing one value per // possible CPU into a buffer of bytes. // // Values are initialized to zero if the slice has less elements than CPUs. -func marshalSlice(slice any, elemLength, possibleCPUs, alignedElemLength int, buf []byte) error { +func appendPerCPUSlice(buf []byte, slice any, possibleCPUs, elemLength, alignedElemLength int) ([]byte, error) { sliceType := reflect.TypeOf(slice) if sliceType.Kind() != reflect.Slice { - return errors.New("per-CPU value requires slice") + return nil, errors.New("per-CPU value requires slice") } sliceValue := reflect.ValueOf(slice) sliceLen := sliceValue.Len() if sliceLen > possibleCPUs { - return fmt.Errorf("per-CPU value exceeds number of CPUs") + return nil, fmt.Errorf("per-CPU value exceeds number of CPUs") } + // Grow increases the slice's capacity, _if_necessary_ + buf = slices.Grow(buf, alignedElemLength*possibleCPUs) for i := 0; i < sliceLen; i++ { elem := sliceValue.Index(i).Interface() elemBytes, err := sysenc.Marshal(elem, elemLength) if err != nil { - return err + return nil, err } - offset := i * alignedElemLength - elemBytes.CopyTo(buf[offset : offset+elemLength]) + b := make([]byte, alignedElemLength) + elemBytes.CopyTo(b) // Only copies elemLength + buf = append(buf, b...) } - return nil + return buf, nil } // marshalPerCPUValue encodes a slice containing one value per @@ -83,8 +87,9 @@ func marshalPerCPUValue(slice any, elemLength int) (sys.Pointer, error) { } alignedElemLength := internal.Align(elemLength, 8) - buf := make([]byte, alignedElemLength*possibleCPUs) - if err := marshalSlice(slice, elemLength, possibleCPUs, alignedElemLength, buf); err != nil { + buf := make([]byte, 0, alignedElemLength*possibleCPUs) + buf, err = appendPerCPUSlice(buf, slice, possibleCPUs, elemLength, alignedElemLength) + if err != nil { return sys.Pointer{}, err } @@ -108,18 +113,15 @@ func marshalBatchPerCPUValue(slice any, batchLen, elemLength int) (sys.Pointer, } alignedElemLength := internal.Align(elemLength, 8) - stride := alignedElemLength * possibleCPUs - result := make([]byte, batchLen*stride) - buf := result + buf := make([]byte, 0, batchLen*alignedElemLength*possibleCPUs) for i := 0; i < batchLen; i++ { batch := sliceValue.Slice(i*possibleCPUs, (i+1)*possibleCPUs).Interface() - if err := marshalSlice(batch, elemLength, possibleCPUs, alignedElemLength, buf[:stride]); err != nil { + buf, err = appendPerCPUSlice(buf, batch, possibleCPUs, elemLength, alignedElemLength) + if err != nil { return sys.Pointer{}, fmt.Errorf("batch %d: %w", i, err) } - - buf = buf[stride:] } - return sys.NewSlicePointer(result), nil + return sys.NewSlicePointer(buf), nil } // unmarshalPerCPUValue decodes a buffer into a slice containing one value per