diff --git a/inmem.go b/inmem.go index 024d0d1..d1eb9c9 100644 --- a/inmem.go +++ b/inmem.go @@ -10,8 +10,6 @@ import ( "time" ) -var spaceReplacer = strings.NewReplacer(" ", "_") - // InmemSink provides a MetricSink that does in-memory aggregation // without sending metrics over a network. It can be embedded within // an application to provide profiling information. @@ -338,13 +336,7 @@ func (i *InmemSink) getInterval() *IntervalMetrics { // Flattens the key for formatting, removes spaces func (i *InmemSink) flattenKey(parts []string) string { - buf := &bytes.Buffer{} - - joined := strings.Join(parts, ".") - - spaceReplacer.WriteString(buf, joined) - - return buf.String() + return strings.Replace(strings.Join(parts, "."), " ", "_", -1) } // Flattens the key for formatting along with its labels, removes spaces @@ -353,8 +345,11 @@ func (i *InmemSink) flattenKeyLabels(parts []string, labels []Label) (string, st buf := bytes.NewBufferString(key) for _, label := range labels { - spaceReplacer.WriteString(buf, fmt.Sprintf(";%s=%s", label.Name, label.Value)) + buf.WriteByte(';') + buf.WriteString(label.Name) + buf.WriteByte('=') + buf.WriteString(label.Value) } - return buf.String(), key + return strings.Replace(buf.String(), " ", "_", -1), key } diff --git a/inmem_test.go b/inmem_test.go index 3b037c7..0e264aa 100644 --- a/inmem_test.go +++ b/inmem_test.go @@ -188,3 +188,69 @@ func duration(t *testing.T, s string) time.Duration { } return dur } + +func BenchmarkFlattenKey(b *testing.B) { + cases := []struct { + name string + parts []string + }{ + { + name: "three-segments", + parts: []string{"foo", "bar", "baz"}, + }, + { + name: "five-segments", + parts: []string{"foo", "bar", "baz", "qux", "quux"}, + }, + { + name: "ten-segments", + parts: []string{"foo", "bar", "baz", "qux", "quux", "corge", "grault", "garply", "waldo", "fred"}, + }, + } + + for _, c := range cases { + b.Run(c.name, func(b *testing.B) { + s := &InmemSink{} + for i := 0; i < b.N; i++ { + s.flattenKey(c.parts) + } + }) + } +} + +func BenchmarkFlattenKeyLabels(b *testing.B) { + cases := []struct { + name string + parts []string + labels []Label + }{ + { + name: "three-segments-no-labels", + parts: []string{"foo", "bar", "baz"}, + }, + { + name: "three-segments-one-label", + parts: []string{"foo", "bar", "baz"}, + labels: []Label{{"blah", "arg"}}, + }, + { + name: "five-segments-three-labels", + parts: []string{"foo", "bar", "baz", "qux", "quux"}, + labels: []Label{{"blah1", "arg1"}, {"blah2", "arg2"}, {"blah3", "arg3"}}, + }, + { + name: "ten-segments-five-labels", + parts: []string{"foo", "bar", "baz", "qux", "quux", "corge", "grault", "garply", "waldo", "fred"}, + labels: []Label{{"blah1", "arg1"}, {"blah2", "arg2"}, {"blah3", "arg3"}, {"blah4", "arg4"}, {"blah5", "arg5"}}, + }, + } + + for _, c := range cases { + b.Run(c.name, func(b *testing.B) { + s := &InmemSink{} + for i := 0; i < b.N; i++ { + s.flattenKeyLabels(c.parts, c.labels) + } + }) + } +}