From 95213692485d6fc06d73e25dc624ca418c8e5858 Mon Sep 17 00:00:00 2001 From: sapslaj Date: Thu, 5 Jan 2023 10:23:41 -0500 Subject: [PATCH] More better ParseMetric performance! Turns out `strings.Builder` is actually pretty efficient! That along with not calling `New()` and instead just calling `make(Labels)` directly the ns/op time is cut in half for `ParseMetric`. --- lokiclient/labels/labels.go | 20 +++++++++++++------- lokiclient/labels/labels_test.go | 9 +++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lokiclient/labels/labels.go b/lokiclient/labels/labels.go index 83f517e..cd8362a 100644 --- a/lokiclient/labels/labels.go +++ b/lokiclient/labels/labels.go @@ -6,6 +6,7 @@ import ( "encoding/json" "sort" "strconv" + "strings" "github.com/cespare/xxhash/v2" "github.com/prometheus/common/model" @@ -448,8 +449,9 @@ func (ls Labels) ReleaseStrings(release func(string)) { func ParseMetric(s string) (result Labels, err error) { var parsingKey bool var parsingValue bool - result = New() - l := Label{} + result = make(Labels, 0) + var name strings.Builder + var value strings.Builder for pos := 0; pos < len(s); pos++ { b := s[pos] if !parsingKey && !parsingValue { @@ -478,24 +480,28 @@ func ParseMetric(s string) (result Labels, err error) { if b == ' ' { continue } - l.Name += string(b) + name.WriteByte(b) } if parsingValue { if b == '"' { parsingValue = false - result = append(result, l) - l = Label{} + result = append(result, Label{ + Name: name.String(), + Value: value.String(), + }) + name.Reset() + value.Reset() continue } if b == '\\' { peek := s[pos+1] if peek == '"' { - l.Value += "\"" + value.WriteRune('"') pos += 1 continue } } - l.Value += string(b) + value.WriteByte(b) } } return diff --git a/lokiclient/labels/labels_test.go b/lokiclient/labels/labels_test.go index ef12e06..92b0843 100644 --- a/lokiclient/labels/labels_test.go +++ b/lokiclient/labels/labels_test.go @@ -788,3 +788,12 @@ func TestParseMetric(t *testing.T) { } } } + +func BenchmarkParseMetric(b *testing.B) { + s := "{foo=\"bar\", bar=\"baz\"}" + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ParseMetric(s) + } +}