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 <mail@olegzaytsev.com>
This commit is contained in:
Oleg Zaytsev 2024-05-09 10:00:24 +02:00
parent 6ebda5a7bc
commit b7b4355807
No known key found for this signature in database
GPG Key ID: 7E9FE9FD48F512EF
1 changed files with 11 additions and 12 deletions

View File

@ -14,8 +14,8 @@
package labels package labels
import ( import (
"bytes"
"strconv" "strconv"
"unsafe"
) )
// MatchType is an enum for label matching types. // 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 { func (m *Matcher) String() string {
const quote = 1 // Start a buffer with a pre-allocated size on stack to cover most needs.
const matcher = 2 var bytea [1024]byte
// As we're not on go1.22 yet and we don't have the new fancy AvailableBuffer method on strings.Builder, b := bytes.NewBuffer(bytea[:0])
// 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)
if m.shouldQuoteName() { if m.shouldQuoteName() {
b = strconv.AppendQuote(b, m.Name) b.Write(strconv.AppendQuote(b.AvailableBuffer(), m.Name))
} else { } else {
b = append(b, m.Name...) b.WriteString(m.Name)
} }
b = append(b, m.Type.String()...) b.WriteString(m.Type.String())
b = strconv.AppendQuote(b, m.Value) b.Write(strconv.AppendQuote(b.AvailableBuffer(), m.Value))
return *((*string)(unsafe.Pointer(&b)))
return b.String()
} }
func (m *Matcher) shouldQuoteName() bool { func (m *Matcher) shouldQuoteName() bool {