mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Avoid copying of the COWMetric if we already have the metric available.
This commit is contained in:
parent
9e7c3e3bcd
commit
17443d288b
|
@ -514,12 +514,11 @@ func histogramQuantileImpl(timestamp clientmodel.Timestamp, args []Node) interfa
|
||||||
// TODO(beorn7): Issue a warning somehow.
|
// TODO(beorn7): Issue a warning somehow.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO avoid copying each time by using a custom fingerprint
|
fp := bucketFingerprint(el.Metric.Metric)
|
||||||
el.Metric.Delete(clientmodel.BucketLabel)
|
|
||||||
el.Metric.Delete(clientmodel.MetricNameLabel)
|
|
||||||
fp := el.Metric.Metric.Fingerprint()
|
|
||||||
mb, ok := fpToMetricWithBuckets[fp]
|
mb, ok := fpToMetricWithBuckets[fp]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
el.Metric.Delete(clientmodel.BucketLabel)
|
||||||
|
el.Metric.Delete(clientmodel.MetricNameLabel)
|
||||||
mb = &metricWithBuckets{el.Metric, nil}
|
mb = &metricWithBuckets{el.Metric, nil}
|
||||||
fpToMetricWithBuckets[fp] = mb
|
fpToMetricWithBuckets[fp] = mb
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package ast
|
package ast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"hash/fnv"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
@ -97,3 +99,46 @@ func quantile(q clientmodel.SampleValue, buckets buckets) float64 {
|
||||||
}
|
}
|
||||||
return bucketStart + (bucketEnd-bucketStart)*float64(rank/count)
|
return bucketStart + (bucketEnd-bucketStart)*float64(rank/count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bucketFingerprint works like the Fingerprint method of Metric, but ignores
|
||||||
|
// the name and the bucket label.
|
||||||
|
func bucketFingerprint(m clientmodel.Metric) clientmodel.Fingerprint {
|
||||||
|
numLabels := 0
|
||||||
|
if len(m) > 2 {
|
||||||
|
numLabels = len(m) - 2
|
||||||
|
}
|
||||||
|
labelNames := make([]string, 0, numLabels)
|
||||||
|
maxLength := 0
|
||||||
|
|
||||||
|
for labelName, labelValue := range m {
|
||||||
|
if labelName == clientmodel.MetricNameLabel || labelName == clientmodel.BucketLabel {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
labelNames = append(labelNames, string(labelName))
|
||||||
|
if len(labelName) > maxLength {
|
||||||
|
maxLength = len(labelName)
|
||||||
|
}
|
||||||
|
if len(labelValue) > maxLength {
|
||||||
|
maxLength = len(labelValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(labelNames)
|
||||||
|
|
||||||
|
summer := fnv.New64a()
|
||||||
|
buf := make([]byte, maxLength)
|
||||||
|
|
||||||
|
for _, labelName := range labelNames {
|
||||||
|
labelValue := m[clientmodel.LabelName(labelName)]
|
||||||
|
|
||||||
|
copy(buf, labelName)
|
||||||
|
summer.Write(buf[:len(labelName)])
|
||||||
|
summer.Write([]byte{clientmodel.SeparatorByte})
|
||||||
|
|
||||||
|
copy(buf, labelValue)
|
||||||
|
summer.Write(buf[:len(labelValue)])
|
||||||
|
summer.Write([]byte{clientmodel.SeparatorByte})
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientmodel.Fingerprint(binary.LittleEndian.Uint64(summer.Sum(nil)))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue