Efficient iteration and search in HashForLabels and HashWithoutLabels (#5707)

* Efficient iteration and search in Labels.HashForLabels

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Better names for variables

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* HashWithoutLabels optimizations

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Refactor HashForLabels and HashWithoutLabels to take sorted names

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>

* Fix review comments

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
This commit is contained in:
Ganesh Vernekar 2019-06-28 18:22:51 +05:30 committed by GitHub
parent 06bdaf076f
commit 588eb20018
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 35 deletions

View file

@ -131,44 +131,46 @@ func (ls Labels) Hash() uint64 {
}
// HashForLabels returns a hash value for the labels matching the provided names.
func (ls Labels) HashForLabels(names ...string) uint64 {
b := make([]byte, 0, 1024)
for _, v := range ls {
for _, n := range names {
if v.Name == n {
b = append(b, v.Name...)
b = append(b, sep)
b = append(b, v.Value...)
b = append(b, sep)
break
}
// 'names' have to be sorted in ascending order.
func (ls Labels) HashForLabels(b []byte, names ...string) (uint64, []byte) {
b = b[:0]
i, j := 0, 0
for i < len(ls) && j < len(names) {
if names[j] < ls[i].Name {
j++
} else if ls[i].Name < names[j] {
i++
} else {
b = append(b, ls[i].Name...)
b = append(b, sep)
b = append(b, ls[i].Value...)
b = append(b, sep)
i++
j++
}
}
return xxhash.Sum64(b)
return xxhash.Sum64(b), b
}
// HashWithoutLabels returns a hash value for all labels except those matching
// the provided names.
func (ls Labels) HashWithoutLabels(names ...string) uint64 {
b := make([]byte, 0, 1024)
Outer:
for _, v := range ls {
if v.Name == MetricName {
// 'names' have to be sorted in ascending order.
func (ls Labels) HashWithoutLabels(b []byte, names ...string) (uint64, []byte) {
b = b[:0]
j := 0
for i := range ls {
for j < len(names) && names[j] < ls[i].Name {
j++
}
if ls[i].Name == MetricName || (j < len(names) && ls[i].Name == names[j]) {
continue
}
for _, n := range names {
if v.Name == n {
continue Outer
}
}
b = append(b, v.Name...)
b = append(b, ls[i].Name...)
b = append(b, sep)
b = append(b, v.Value...)
b = append(b, ls[i].Value...)
b = append(b, sep)
}
return xxhash.Sum64(b)
return xxhash.Sum64(b), b
}
// Copy returns a copy of the labels.

View file

@ -1523,13 +1523,17 @@ func (ev *evaluator) VectorBinop(op ItemType, lhs, rhs Vector, matching *VectorM
// signatureFunc returns a function that calculates the signature for a metric
// ignoring the provided labels. If on, then the given labels are only used instead.
func signatureFunc(on bool, names ...string) func(labels.Labels) uint64 {
// TODO(fabxc): ensure names are sorted and then use that and sortedness
// of labels by names to speed up the operations below.
// Alternatively, inline the hashing and don't build new label sets.
sort.Strings(names)
if on {
return func(lset labels.Labels) uint64 { return lset.HashForLabels(names...) }
return func(lset labels.Labels) uint64 {
h, _ := lset.HashForLabels(make([]byte, 0, 1024), names...)
return h
}
}
return func(lset labels.Labels) uint64 {
h, _ := lset.HashWithoutLabels(make([]byte, 0, 1024), names...)
return h
}
return func(lset labels.Labels) uint64 { return lset.HashWithoutLabels(names...) }
}
// resultMetric returns the metric for the given sample(s) based on the Vector
@ -1722,8 +1726,9 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
}
}
sort.Strings(grouping)
lb := labels.NewBuilder(nil)
buf := make([]byte, 0, 1024)
for _, s := range vec {
metric := s.Metric
@ -1737,9 +1742,9 @@ func (ev *evaluator) aggregation(op ItemType, grouping []string, without bool, p
groupingKey uint64
)
if without {
groupingKey = metric.HashWithoutLabels(grouping...)
groupingKey, buf = metric.HashWithoutLabels(buf, grouping...)
} else {
groupingKey = metric.HashForLabels(grouping...)
groupingKey, buf = metric.HashForLabels(buf, grouping...)
}
group, ok := result[groupingKey]