Browse Source

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>
pull/4389/head
Ganesh Vernekar 5 years ago committed by GitHub
parent
commit
588eb20018
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 56
      pkg/labels/labels.go
  2. 21
      promql/engine.go

56
pkg/labels/labels.go

@ -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 {
continue
// '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++
}
for _, n := range names {
if v.Name == n {
continue Outer
}
if ls[i].Name == MetricName || (j < len(names) && ls[i].Name == names[j]) {
continue
}
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.

21
promql/engine.go

@ -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]

Loading…
Cancel
Save