From 33aab1b2cc9009e60d1ae0658ffe66db84ed6698 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sun, 13 Aug 2023 14:55:50 +0100 Subject: [PATCH 1/2] labels: extend benchmark for Has() Signed-off-by: Bryan Boreham --- model/labels/labels_test.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/model/labels/labels_test.go b/model/labels/labels_test.go index d91be27cb..a5401b924 100644 --- a/model/labels/labels_test.go +++ b/model/labels/labels_test.go @@ -472,16 +472,22 @@ func BenchmarkLabels_Get(b *testing.B) { for _, scenario := range []struct { desc, label string }{ - {"get first label", allLabels[0].Name}, - {"get middle label", allLabels[size/2].Name}, - {"get last label", allLabels[size-1].Name}, - {"get not-found label", "benchmark"}, + {"first label", allLabels[0].Name}, + {"middle label", allLabels[size/2].Name}, + {"last label", allLabels[size-1].Name}, + {"not-found label", "benchmark"}, } { b.Run(scenario.desc, func(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = labels.Get(scenario.label) - } + b.Run("get", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = labels.Get(scenario.label) + } + }) + b.Run("has", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = labels.Has(scenario.label) + } + }) }) } }) From b5c6807fea172ffcc55359d3ea042bcc7b13bab2 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sun, 13 Aug 2023 14:56:15 +0100 Subject: [PATCH 2/2] Labels.Has quick check on first character Exit early if we've gone past - labels are sorted in order. Signed-off-by: Bryan Boreham --- model/labels/labels_stringlabels.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/model/labels/labels_stringlabels.go b/model/labels/labels_stringlabels.go index 223aa6ebf..bc4700eaa 100644 --- a/model/labels/labels_stringlabels.go +++ b/model/labels/labels_stringlabels.go @@ -300,13 +300,26 @@ func (ls Labels) Get(name string) string { // Has returns true if the label with the given name is present. func (ls Labels) Has(name string) bool { + if name == "" { // Avoid crash in loop if someone asks for "". + return false // Prometheus does not store blank label names. + } for i := 0; i < len(ls.data); { - var lName string - lName, i = decodeString(ls.data, i) - _, i = decodeString(ls.data, i) - if lName == name { - return true + var size int + size, i = decodeSize(ls.data, i) + if ls.data[i] == name[0] { + lName := ls.data[i : i+size] + i += size + if lName == name { + return true + } + } else { + if ls.data[i] > name[0] { // Stop looking if we've gone past. + break + } + i += size } + size, i = decodeSize(ls.data, i) + i += size } return false }