labels: use slices.Sort for better performance

The difference is modest, but we've used `slices.Sort` in lots of other
places so why not here.

name     old time/op    new time/op    delta
Builder    1.04µs ± 3%    0.95µs ± 3%   -8.27%  (p=0.008 n=5+5)

name     old alloc/op   new alloc/op   delta
Builder      312B ± 0%      288B ± 0%   -7.69%  (p=0.008 n=5+5)

name     old allocs/op  new allocs/op  delta
Builder      2.00 ± 0%      1.00 ± 0%  -50.00%  (p=0.008 n=5+5)

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
Bryan Boreham 2023-03-06 18:22:49 +00:00
parent a07a0be024
commit 38c6d3da9f
2 changed files with 11 additions and 11 deletions

View file

@ -18,11 +18,11 @@ package labels
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"sort"
"strconv" "strconv"
"github.com/cespare/xxhash/v2" "github.com/cespare/xxhash/v2"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
"golang.org/x/exp/slices"
) )
// Well-known label names used by Prometheus components. // Well-known label names used by Prometheus components.
@ -360,7 +360,7 @@ func EmptyLabels() Labels {
func New(ls ...Label) Labels { func New(ls ...Label) Labels {
set := make(Labels, 0, len(ls)) set := make(Labels, 0, len(ls))
set = append(set, ls...) set = append(set, ls...)
sort.Sort(set) slices.SortFunc(set, func(a, b Label) bool { return a.Name < b.Name })
return set return set
} }
@ -384,7 +384,7 @@ func FromStrings(ss ...string) Labels {
res = append(res, Label{Name: ss[i], Value: ss[i+1]}) res = append(res, Label{Name: ss[i], Value: ss[i+1]})
} }
sort.Sort(res) slices.SortFunc(res, func(a, b Label) bool { return a.Name < b.Name })
return res return res
} }
@ -564,7 +564,7 @@ Outer:
} }
if len(b.add) > 0 { // Base is already in order, so we only need to sort if we add to it. if len(b.add) > 0 { // Base is already in order, so we only need to sort if we add to it.
res = append(res, b.add...) res = append(res, b.add...)
sort.Sort(res) slices.SortFunc(res, func(a, b Label) bool { return a.Name < b.Name })
} }
return res return res
} }
@ -591,7 +591,7 @@ func (b *ScratchBuilder) Add(name, value string) {
// Sort the labels added so far by name. // Sort the labels added so far by name.
func (b *ScratchBuilder) Sort() { func (b *ScratchBuilder) Sort() {
sort.Sort(b.add) slices.SortFunc(b.add, func(a, b Label) bool { return a.Name < b.Name })
} }
// Asssign is for when you already have a Labels which you want this ScratchBuilder to return. // Asssign is for when you already have a Labels which you want this ScratchBuilder to return.

View file

@ -19,12 +19,12 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"reflect" "reflect"
"sort"
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/cespare/xxhash/v2" "github.com/cespare/xxhash/v2"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
"golang.org/x/exp/slices"
) )
// Well-known label names used by Prometheus components. // Well-known label names used by Prometheus components.
@ -385,7 +385,7 @@ func yoloBytes(s string) (b []byte) {
// New returns a sorted Labels from the given labels. // New returns a sorted Labels from the given labels.
// The caller has to guarantee that all label names are unique. // The caller has to guarantee that all label names are unique.
func New(ls ...Label) Labels { func New(ls ...Label) Labels {
sort.Sort(labelSlice(ls)) slices.SortFunc(ls, func(a, b Label) bool { return a.Name < b.Name })
size := labelsSize(ls) size := labelsSize(ls)
buf := make([]byte, size) buf := make([]byte, size)
marshalLabelsToSizedBuffer(ls, buf) marshalLabelsToSizedBuffer(ls, buf)
@ -411,7 +411,7 @@ func FromStrings(ss ...string) Labels {
ls = append(ls, Label{Name: ss[i], Value: ss[i+1]}) ls = append(ls, Label{Name: ss[i], Value: ss[i+1]})
} }
sort.Sort(labelSlice(ls)) slices.SortFunc(ls, func(a, b Label) bool { return a.Name < b.Name })
return New(ls...) return New(ls...)
} }
@ -595,8 +595,8 @@ func (b *Builder) Labels(res Labels) Labels {
return b.base return b.base
} }
sort.Sort(labelSlice(b.add)) slices.SortFunc(b.add, func(a, b Label) bool { return a.Name < b.Name })
sort.Strings(b.del) slices.Sort(b.del)
a, d := 0, 0 a, d := 0, 0
buf := make([]byte, 0, len(b.base.data)) // TODO: see if we can re-use the buffer from res. buf := make([]byte, 0, len(b.base.data)) // TODO: see if we can re-use the buffer from res.
@ -753,7 +753,7 @@ func (b *ScratchBuilder) Add(name, value string) {
// Sort the labels added so far by name. // Sort the labels added so far by name.
func (b *ScratchBuilder) Sort() { func (b *ScratchBuilder) Sort() {
sort.Sort(labelSlice(b.add)) slices.SortFunc(b.add, func(a, b Label) bool { return a.Name < b.Name })
} }
// Asssign is for when you already have a Labels which you want this ScratchBuilder to return. // Asssign is for when you already have a Labels which you want this ScratchBuilder to return.