5
5
"errors"
6
6
"fmt"
7
7
"reflect"
8
+ "slices"
8
9
"unsafe"
9
10
10
11
"github.com/cilium/ebpf/internal"
@@ -43,33 +44,36 @@ func makeMapSyscallOutput(dst any, length int) sysenc.Buffer {
43
44
return sysenc .SyscallOutput (dst , length )
44
45
}
45
46
46
- // marshalSlice encodes a slice containing one value per
47
+ // appendPerCPUSlice encodes a slice containing one value per
47
48
// possible CPU into a buffer of bytes.
48
49
//
49
50
// Values are initialized to zero if the slice has less elements than CPUs.
50
- func marshalSlice ( slice any , elemLength , possibleCPUs , alignedElemLength int , buf []byte ) error {
51
+ func appendPerCPUSlice ( buf [] byte , slice any , possibleCPUs , elemLength , alignedElemLength int ) ( []byte , error ) {
51
52
sliceType := reflect .TypeOf (slice )
52
53
if sliceType .Kind () != reflect .Slice {
53
- return errors .New ("per-CPU value requires slice" )
54
+ return nil , errors .New ("per-CPU value requires slice" )
54
55
}
55
56
56
57
sliceValue := reflect .ValueOf (slice )
57
58
sliceLen := sliceValue .Len ()
58
59
if sliceLen > possibleCPUs {
59
- return fmt .Errorf ("per-CPU value exceeds number of CPUs" )
60
+ return nil , fmt .Errorf ("per-CPU value exceeds number of CPUs" )
60
61
}
61
62
63
+ // Grow increases the slice's capacity, _if_necessary_
64
+ buf = slices .Grow (buf , alignedElemLength * possibleCPUs )
62
65
for i := 0 ; i < sliceLen ; i ++ {
63
66
elem := sliceValue .Index (i ).Interface ()
64
67
elemBytes , err := sysenc .Marshal (elem , elemLength )
65
68
if err != nil {
66
- return err
69
+ return nil , err
67
70
}
68
71
69
- offset := i * alignedElemLength
70
- elemBytes .CopyTo (buf [offset : offset + elemLength ])
72
+ b := make ([]byte , alignedElemLength )
73
+ elemBytes .CopyTo (b ) // Only copies elemLength
74
+ buf = append (buf , b ... )
71
75
}
72
- return nil
76
+ return buf , nil
73
77
}
74
78
75
79
// marshalPerCPUValue encodes a slice containing one value per
@@ -83,8 +87,9 @@ func marshalPerCPUValue(slice any, elemLength int) (sys.Pointer, error) {
83
87
}
84
88
85
89
alignedElemLength := internal .Align (elemLength , 8 )
86
- buf := make ([]byte , alignedElemLength * possibleCPUs )
87
- if err := marshalSlice (slice , elemLength , possibleCPUs , alignedElemLength , buf ); err != nil {
90
+ buf := make ([]byte , 0 , alignedElemLength * possibleCPUs )
91
+ buf , err = appendPerCPUSlice (buf , slice , possibleCPUs , elemLength , alignedElemLength )
92
+ if err != nil {
88
93
return sys.Pointer {}, err
89
94
}
90
95
@@ -108,18 +113,15 @@ func marshalBatchPerCPUValue(slice any, batchLen, elemLength int) (sys.Pointer,
108
113
}
109
114
110
115
alignedElemLength := internal .Align (elemLength , 8 )
111
- stride := alignedElemLength * possibleCPUs
112
- result := make ([]byte , batchLen * stride )
113
- buf := result
116
+ buf := make ([]byte , 0 , batchLen * alignedElemLength * possibleCPUs )
114
117
for i := 0 ; i < batchLen ; i ++ {
115
118
batch := sliceValue .Slice (i * possibleCPUs , (i + 1 )* possibleCPUs ).Interface ()
116
- if err := marshalSlice (batch , elemLength , possibleCPUs , alignedElemLength , buf [:stride ]); err != nil {
119
+ buf , err = appendPerCPUSlice (buf , batch , possibleCPUs , elemLength , alignedElemLength )
120
+ if err != nil {
117
121
return sys.Pointer {}, fmt .Errorf ("batch %d: %w" , i , err )
118
122
}
119
-
120
- buf = buf [stride :]
121
123
}
122
- return sys .NewSlicePointer (result ), nil
124
+ return sys .NewSlicePointer (buf ), nil
123
125
}
124
126
125
127
// unmarshalPerCPUValue decodes a buffer into a slice containing one value per
0 commit comments