Skip to content

Commit 79455b0

Browse files
authored
Merge pull request #346 from bobrik/ivan/decoder-cache-partition
Partition decoder cache by name
2 parents 88f7446 + 4045932 commit 79455b0

File tree

4 files changed

+79
-13
lines changed

4 files changed

+79
-13
lines changed

decoder/decoder.go

+12-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type Decoder interface {
2323
type Set struct {
2424
mu sync.Mutex
2525
decoders map[string]Decoder
26-
cache map[string][]string
26+
cache map[string]map[string][]string
2727
}
2828

2929
// NewSet creates a Set with all known decoders
@@ -57,7 +57,7 @@ func NewSet() (*Set, error) {
5757
"syscall": &Syscall{},
5858
"uint": &UInt{},
5959
},
60-
cache: map[string][]string{},
60+
cache: map[string]map[string][]string{},
6161
}, nil
6262
}
6363

@@ -85,14 +85,20 @@ func (s *Set) decode(in []byte, label config.Label) ([]byte, error) {
8585
}
8686

8787
// DecodeLabels transforms eBPF map key bytes into a list of label values
88-
// according to configuration
89-
func (s *Set) DecodeLabels(in []byte, labels []config.Label) ([]string, error) {
88+
// according to configuration (different label sets require different names)
89+
func (s *Set) DecodeLabels(in []byte, name string, labels []config.Label) ([]string, error) {
9090
s.mu.Lock()
9191
defer s.mu.Unlock()
9292

93+
cache, ok := s.cache[name]
94+
if !ok {
95+
cache = map[string][]string{}
96+
s.cache[name] = cache
97+
}
98+
9399
// string(in) must not be a variable to avoid allocation:
94100
// * https://github.com/golang/go/commit/f5f5a8b6209f8
95-
if cached, ok := s.cache[string(in)]; ok {
101+
if cached, ok := cache[string(in)]; ok {
96102
return cached, nil
97103
}
98104

@@ -101,7 +107,7 @@ func (s *Set) DecodeLabels(in []byte, labels []config.Label) ([]string, error) {
101107
return nil, err
102108
}
103109

104-
s.cache[string(in)] = values
110+
cache[string(in)] = values
105111

106112
return values, nil
107113
}

decoder/decoder_test.go

+65-5
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,13 @@ func TestDecodeLabels(t *testing.T) {
121121
},
122122
}
123123

124-
for _, c := range cases {
124+
for i, c := range cases {
125125
s, err := NewSet()
126126
if err != nil {
127127
t.Fatal(err)
128128
}
129129

130-
out, err := s.DecodeLabels(c.in, c.labels)
130+
out, err := s.DecodeLabels(c.in, fmt.Sprintf("test:%d", i), c.labels)
131131
if c.err {
132132
if err == nil {
133133
t.Errorf("Expected error for input %#v and labels %#v, but did not receive it", c.in, c.labels)
@@ -152,7 +152,7 @@ func TestDecodeLabels(t *testing.T) {
152152
}
153153
}
154154

155-
func TestConcurrency(t *testing.T) {
155+
func TestDecoderSetConcurrency(t *testing.T) {
156156
in := append([]byte{0x8, 0x0, 0x0, 0x0}, zeroPaddedString("bananas", 32)...)
157157

158158
labels := []config.Label{
@@ -197,7 +197,7 @@ func TestConcurrency(t *testing.T) {
197197
go func() {
198198
defer wg.Done()
199199

200-
_, err := s.DecodeLabels(in, labels)
200+
_, err := s.DecodeLabels(in, "concurrency", labels)
201201
if err != nil {
202202
t.Error(err)
203203
}
@@ -207,6 +207,66 @@ func TestConcurrency(t *testing.T) {
207207
wg.Wait()
208208
}
209209

210+
func TestDecoderSetCache(t *testing.T) {
211+
in := []byte{0xba, 0xbe, 0xba, 0xbe, 0xde, 0xad, 0xbe, 0xef}
212+
213+
one := []config.Label{
214+
{
215+
Name: "single_u64",
216+
Size: 8,
217+
Decoders: []config.Decoder{
218+
{
219+
Name: "uint",
220+
},
221+
},
222+
},
223+
}
224+
225+
two := []config.Label{
226+
{
227+
Name: "u32_one",
228+
Size: 4,
229+
Decoders: []config.Decoder{
230+
{
231+
Name: "uint",
232+
},
233+
},
234+
},
235+
{
236+
Name: "u32_two",
237+
Size: 4,
238+
Decoders: []config.Decoder{
239+
{
240+
Name: "uint",
241+
},
242+
},
243+
},
244+
}
245+
246+
s, err := NewSet()
247+
if err != nil {
248+
t.Fatal(err)
249+
}
250+
251+
single, err := s.DecodeLabels(in, "one", one)
252+
if err != nil {
253+
t.Fatal(err)
254+
}
255+
256+
if len(single) != 1 {
257+
t.Errorf("Expected one u64 from %#v, got %#v", one, single)
258+
}
259+
260+
double, err := s.DecodeLabels(in, "two", two)
261+
if err != nil {
262+
t.Error(err)
263+
}
264+
265+
if len(double) != 2 {
266+
t.Errorf("Expected two u32 from %#v, got %#v", two, double)
267+
}
268+
}
269+
210270
func BenchmarkCache(b *testing.B) {
211271
in := []byte{
212272
0x8, 0xab, 0xce, 0xef,
@@ -270,7 +330,7 @@ func BenchmarkCache(b *testing.B) {
270330

271331
b.Run("cached", func(b *testing.B) {
272332
for i := 0; i < b.N; i++ {
273-
_, err := s.DecodeLabels(in, labels)
333+
_, err := s.DecodeLabels(in, "test", labels)
274334
if err != nil {
275335
b.Fatal(err)
276336
}

exporter/exporter.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ func (e *Exporter) mapValues(module *libbpfgo.Module, name string, labels []conf
438438
raw = raw[4:]
439439
}
440440

441-
metricValues[i].labels, err = e.decoders.DecodeLabels(raw, labels)
441+
metricValues[i].labels, err = e.decoders.DecodeLabels(raw, name, labels)
442442
if err != nil {
443443
if err == decoder.ErrSkipLabelSet {
444444
continue

exporter/perf_event_array.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func newPerfEventArraySink(decoders *decoder.Set, module *libbpfgo.Module, count
4343
validDataSize += labelConfig.Size
4444
}
4545

46-
labelValues, err := decoders.DecodeLabels(rawBytes[:validDataSize], sink.counterConfig.Labels)
46+
labelValues, err := decoders.DecodeLabels(rawBytes[:validDataSize], counterConfig.Name, sink.counterConfig.Labels)
4747
if err != nil {
4848
if err == decoder.ErrSkipLabelSet {
4949
continue

0 commit comments

Comments
 (0)