Fix label sorting benchmark
This commit is contained in:
parent
9a9e46611e
commit
51ea34d381
|
@ -141,3 +141,10 @@ func Compare(a, b Labels) int {
|
||||||
// If all labels so far were in common, the set with fewer labels comes first.
|
// If all labels so far were in common, the set with fewer labels comes first.
|
||||||
return len(a) - len(b)
|
return len(a) - len(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slice is a sortable slice of label sets.
|
||||||
|
type Slice []Labels
|
||||||
|
|
||||||
|
func (s Slice) Len() int { return len(s) }
|
||||||
|
func (s Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
func (s Slice) Less(i, j int) bool { return Compare(s[i], s[j]) < 0 }
|
||||||
|
|
|
@ -2,14 +2,16 @@ package labels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/bradfitz/slice"
|
"github.com/pkg/errors"
|
||||||
dto "github.com/prometheus/client_model/go"
|
promlabels "github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/common/expfmt"
|
"github.com/prometheus/prometheus/pkg/textparse"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -76,59 +78,72 @@ func TestCompare(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkLabelsSliceSort(b *testing.B) {
|
func BenchmarkSliceSort(b *testing.B) {
|
||||||
f, err := os.Open("../cmd/tsdb/testdata.100k")
|
lbls, err := readPrometheusLabels("../testdata/1m.series", 900000)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
lbls, err := readPrometheusLabels(f, 5000)
|
for len(lbls) < 20e6 {
|
||||||
require.NoError(b, err)
|
lbls = append(lbls, lbls...)
|
||||||
|
|
||||||
b.Run("", func(b *testing.B) {
|
|
||||||
clbls := make([]Labels, len(lbls))
|
|
||||||
copy(clbls, lbls)
|
|
||||||
|
|
||||||
for i := range clbls {
|
|
||||||
j := rand.Intn(i + 1)
|
|
||||||
clbls[i], clbls[j] = clbls[j], clbls[i]
|
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
for i := range lbls {
|
||||||
|
j := rand.Intn(i + 1)
|
||||||
|
lbls[i], lbls[j] = lbls[j], lbls[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range []int{
|
||||||
|
100, 5000, 50000, 300000, 900000, 5e6, 20e6,
|
||||||
|
} {
|
||||||
|
b.Run(fmt.Sprintf("%d", k), func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for a := 0; a < b.N; a++ {
|
||||||
slice.Sort(clbls, func(i, j int) bool {
|
b.StopTimer()
|
||||||
return Compare(clbls[i], clbls[j]) < 0
|
cl := make(Slice, k)
|
||||||
})
|
copy(cl, Slice(lbls[:k]))
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
sort.Sort(cl)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPrometheusLabels(r io.Reader, n int) ([]Labels, error) {
|
func readPrometheusLabels(fn string, n int) ([]Labels, error) {
|
||||||
dec := expfmt.NewDecoder(r, expfmt.FmtProtoText)
|
f, err := os.Open(fn)
|
||||||
|
if err != nil {
|
||||||
var mets []Labels
|
return nil, err
|
||||||
var mf dto.MetricFamily
|
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
if err := dec.Decode(&mf); err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range mf.GetMetric() {
|
p := textparse.New(b)
|
||||||
met := make([]Label, 0, len(m.GetLabel())+1)
|
i := 0
|
||||||
met = append(met, Label{"__name__", mf.GetName()})
|
var mets []Labels
|
||||||
|
hashes := map[uint64]struct{}{}
|
||||||
|
|
||||||
for _, l := range m.GetLabel() {
|
for p.Next() && i < n {
|
||||||
met = append(met, Label{l.GetName(), l.GetValue()})
|
m := make(Labels, 0, 10)
|
||||||
}
|
p.Metric((*promlabels.Labels)(unsafe.Pointer(&m)))
|
||||||
mets = append(mets, met)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Println("read metrics", len(mets[:n]))
|
|
||||||
|
|
||||||
return mets[:n], nil
|
h := m.Hash()
|
||||||
|
if _, ok := hashes[h]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mets = append(mets, m)
|
||||||
|
hashes[h] = struct{}{}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if err := p.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if i != n {
|
||||||
|
return mets, errors.Errorf("requested %d metrics but found %d", n, i)
|
||||||
|
}
|
||||||
|
return mets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkLabelSetFromMap(b *testing.B) {
|
func BenchmarkLabelSetFromMap(b *testing.B) {
|
||||||
|
|
Loading…
Reference in New Issue