@@ -5,17 +5,16 @@ import (
5
5
"encoding/binary"
6
6
"encoding/hex"
7
7
"fmt"
8
+ "slices"
8
9
"sort"
9
10
"strconv"
10
11
"strings"
11
12
12
13
"github.com/cespare/xxhash/v2"
13
14
pmodel "github.com/prometheus/common/model"
14
15
"github.com/prometheus/prometheus/model/labels"
15
- "github.com/prometheus/prometheus/promql/parser"
16
16
17
17
typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1"
18
- "github.com/grafana/pyroscope/pkg/slices"
19
18
"github.com/grafana/pyroscope/pkg/util"
20
19
)
21
20
@@ -102,52 +101,25 @@ func (ls Labels) Hash() uint64 {
102
101
return xxhash .Sum64 (b )
103
102
}
104
103
105
- // HashForLabels returns a hash value for the labels matching the provided names.
106
- // 'names' have to be sorted in ascending order.
107
- func (ls Labels ) HashForLabels (b []byte , names ... string ) (uint64 , []byte ) {
108
- b = b [:0 ]
109
- i , j := 0 , 0
110
- for i < len (ls ) && j < len (names ) {
111
- if names [j ] < ls [i ].Name {
112
- j ++
113
- } else if ls [i ].Name < names [j ] {
114
- i ++
115
- } else {
116
- b = append (b , ls [i ].Name ... )
117
- b = append (b , seps [0 ])
118
- b = append (b , ls [i ].Value ... )
119
- b = append (b , seps [0 ])
120
- i ++
121
- j ++
122
- }
123
- }
124
- return xxhash .Sum64 (b ), b
125
- }
126
-
127
104
// BytesWithLabels is just as Bytes(), but only for labels matching names.
128
- // 'names' have to be sorted in ascending order.
129
105
// It uses an byte invalid character as a separator and so should not be used for printing.
130
106
func (ls Labels ) BytesWithLabels (buf []byte , names ... string ) []byte {
131
- b := bytes .NewBuffer (buf [:0 ])
132
- b .WriteByte (labelSep )
133
- i , j := 0 , 0
134
- for i < len (ls ) && j < len (names ) {
135
- if names [j ] < ls [i ].Name {
136
- j ++
137
- } else if ls [i ].Name < names [j ] {
138
- i ++
139
- } else {
140
- if b .Len () > 1 {
141
- b .WriteByte (seps [0 ])
107
+ buf = buf [:0 ]
108
+ buf = append (buf , labelSep )
109
+ for _ , name := range names {
110
+ for _ , l := range ls {
111
+ if l .Name == name {
112
+ if len (buf ) > 1 {
113
+ buf = append (buf , seps [0 ])
114
+ }
115
+ buf = append (buf , l .Name ... )
116
+ buf = append (buf , seps [0 ])
117
+ buf = append (buf , l .Value ... )
118
+ break
142
119
}
143
- b .WriteString (ls [i ].Name )
144
- b .WriteByte (seps [0 ])
145
- b .WriteString (ls [i ].Value )
146
- i ++
147
- j ++
148
120
}
149
121
}
150
- return b . Bytes ()
122
+ return buf
151
123
}
152
124
153
125
func (ls Labels ) ToPrometheusLabels () labels.Labels {
@@ -180,22 +152,18 @@ func IsLabelAllowedForIngestion(name string) bool {
180
152
return allowed
181
153
}
182
154
183
- // WithLabels returns a subset of Labels that matches match with the provided label names.
155
+ // WithLabels returns a subset of Labels that match with the provided label names.
184
156
func (ls Labels ) WithLabels (names ... string ) Labels {
185
- matchedLabels := Labels {}
186
-
187
- nameSet := make (map [string ]struct {}, len (names ))
188
- for _ , n := range names {
189
- nameSet [n ] = struct {}{}
190
- }
191
-
192
- for _ , v := range ls {
193
- if _ , ok := nameSet [v .Name ]; ok {
194
- matchedLabels = append (matchedLabels , v )
157
+ matched := make (Labels , 0 , len (names ))
158
+ for _ , name := range names {
159
+ for _ , l := range ls {
160
+ if l .Name == name {
161
+ matched = append (matched , l )
162
+ break
163
+ }
195
164
}
196
165
}
197
-
198
- return matchedLabels
166
+ return matched
199
167
}
200
168
201
169
// Get returns the value for the label with the given name.
@@ -221,37 +189,42 @@ func (ls Labels) GetLabel(name string) (*typesv1.LabelPair, bool) {
221
189
222
190
// Delete removes the first label encountered with the name given in place.
223
191
func (ls Labels ) Delete (name string ) Labels {
224
- return slices .RemoveInPlace (ls , func (pair * typesv1.LabelPair , i int ) bool {
225
- return pair .Name == name
226
- })
192
+ for i , l := range ls {
193
+ if l .Name == name {
194
+ return slices .Delete (ls , i , i + 1 )
195
+ }
196
+ }
197
+ return ls
227
198
}
228
199
229
- // Insert adds the given label to the set of labels.
230
- // It assumes the labels are ordered
231
- func (ls * Labels ) Insert (name , value string ) {
232
- // Find the index where the new label should be inserted
200
+ // InsertSorted adds the given label to the set of labels.
201
+ // It assumes the labels are sorted lexicographically.
202
+ func (ls Labels ) InsertSorted (name , value string ) Labels {
203
+ // Find the index where the new label should be inserted.
204
+ // TODO: Use binary search on large label sets.
233
205
index := - 1
234
- for i , label := range * ls {
206
+ for i , label := range ls {
235
207
if label .Name > name {
236
208
index = i
237
209
break
238
210
}
239
211
if label .Name == name {
240
212
label .Value = value
241
- return
213
+ return ls
242
214
}
243
215
}
244
- // Insert the new label at the found index
216
+ // Insert the new label at the found index.
245
217
l := & typesv1.LabelPair {
246
218
Name : name ,
247
219
Value : value ,
248
220
}
249
- * ls = append (* ls , l )
221
+ c : = append (ls , l )
250
222
if index == - 1 {
251
- return
223
+ return c
252
224
}
253
- copy ((* ls )[index + 1 :], (* ls )[index :])
254
- (* ls )[index ] = l
225
+ copy ((c )[index + 1 :], (c )[index :])
226
+ (c )[index ] = l
227
+ return c
255
228
}
256
229
257
230
func (ls Labels ) Clone () Labels {
@@ -301,22 +274,6 @@ func LabelPairsString(lbs []*typesv1.LabelPair) string {
301
274
return b .String ()
302
275
}
303
276
304
- // StringToLabelsPairs converts a string representation of label pairs to a slice of label pairs.
305
- func StringToLabelsPairs (s string ) ([]* typesv1.LabelPair , error ) {
306
- matchers , err := parser .ParseMetricSelector (s )
307
- if err != nil {
308
- return nil , err
309
- }
310
- result := make ([]* typesv1.LabelPair , len (matchers ))
311
- for i := range matchers {
312
- result [i ] = & typesv1.LabelPair {
313
- Name : matchers [i ].Name ,
314
- Value : matchers [i ].Value ,
315
- }
316
- }
317
- return result , nil
318
- }
319
-
320
277
// LabelsFromStrings creates new labels from pairs of strings.
321
278
func LabelsFromStrings (ss ... string ) Labels {
322
279
if len (ss )% 2 != 0 {
@@ -454,33 +411,6 @@ Outer:
454
411
return append (res , b .add ... )
455
412
}
456
413
457
- // StableHash is a labels hashing implementation which is guaranteed to not change over time.
458
- // This function should be used whenever labels hashing backward compatibility must be guaranteed.
459
- func StableHash (ls labels.Labels ) uint64 {
460
- // Use xxhash.Sum64(b) for fast path as it's faster.
461
- b := make ([]byte , 0 , 1024 )
462
- for i , v := range ls {
463
- if len (b )+ len (v .Name )+ len (v .Value )+ 2 >= cap (b ) {
464
- // If labels entry is 1KB+ do not allocate whole entry.
465
- h := xxhash .New ()
466
- _ , _ = h .Write (b )
467
- for _ , v := range ls [i :] {
468
- _ , _ = h .WriteString (v .Name )
469
- _ , _ = h .Write (seps )
470
- _ , _ = h .WriteString (v .Value )
471
- _ , _ = h .Write (seps )
472
- }
473
- return h .Sum64 ()
474
- }
475
-
476
- b = append (b , v .Name ... )
477
- b = append (b , seps [0 ])
478
- b = append (b , v .Value ... )
479
- b = append (b , seps [0 ])
480
- }
481
- return xxhash .Sum64 (b )
482
- }
483
-
484
414
type SessionID uint64
485
415
486
416
func (s SessionID ) String () string {
0 commit comments