From b7b4355807ca53dbff39dc9ed5baa80a8b34fed4 Mon Sep 17 00:00:00 2001 From: Oleg Zaytsev Date: Thu, 9 May 2024 10:00:24 +0200 Subject: [PATCH] Use bytes.Buffer from stack buf in Matcher.String() Also removed the growing until there's a benchmark for that. Signed-off-by: Oleg Zaytsev --- model/labels/matcher.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/model/labels/matcher.go b/model/labels/matcher.go index ce9e42471..8e220e392 100644 --- a/model/labels/matcher.go +++ b/model/labels/matcher.go @@ -14,8 +14,8 @@ package labels import ( + "bytes" "strconv" - "unsafe" ) // MatchType is an enum for label matching types. @@ -79,20 +79,19 @@ func MustNewMatcher(mt MatchType, name, val string) *Matcher { } func (m *Matcher) String() string { - const quote = 1 - const matcher = 2 - // As we're not on go1.22 yet and we don't have the new fancy AvailableBuffer method on strings.Builder, - // we'll use a plain byte slice and then do the unsafe conversion to string just like strings.Builder does. - // We pre-allocate pessimistically for quoting the label name, and optimistically for not having to escape any quotes. - b := make([]byte, 0, quote+len(m.Name)+quote+matcher+quote+len(m.Value)+quote) + // Start a buffer with a pre-allocated size on stack to cover most needs. + var bytea [1024]byte + b := bytes.NewBuffer(bytea[:0]) + if m.shouldQuoteName() { - b = strconv.AppendQuote(b, m.Name) + b.Write(strconv.AppendQuote(b.AvailableBuffer(), m.Name)) } else { - b = append(b, m.Name...) + b.WriteString(m.Name) } - b = append(b, m.Type.String()...) - b = strconv.AppendQuote(b, m.Value) - return *((*string)(unsafe.Pointer(&b))) + b.WriteString(m.Type.String()) + b.Write(strconv.AppendQuote(b.AvailableBuffer(), m.Value)) + + return b.String() } func (m *Matcher) shouldQuoteName() bool {