mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
perf(nhcb): reuse calculated metric name and hash if possible
We advance the embedded parser one series at a time. Before we advance, we clear any calculated name and hash. During processing we remember if we already calculated the name or hash. Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
This commit is contained in:
parent
bcb1213010
commit
bb5746c3e4
|
@ -36,6 +36,15 @@ const (
|
||||||
stateEmitting
|
stateEmitting
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Keep track of what information we have already loaded about the next series.
|
||||||
|
type histogramInfoPreloaded struct {
|
||||||
|
hasName bool // The metricName and suffix is loaded.
|
||||||
|
hasHash bool // The hash was calculated.
|
||||||
|
metricName string // Without magic suffixes.
|
||||||
|
suffixType convertnhcb.SuffixType
|
||||||
|
hash uint64
|
||||||
|
}
|
||||||
|
|
||||||
// The NHCBParser wraps a Parser and converts classic histograms to native
|
// The NHCBParser wraps a Parser and converts classic histograms to native
|
||||||
// histograms with custom buckets.
|
// histograms with custom buckets.
|
||||||
//
|
//
|
||||||
|
@ -59,6 +68,9 @@ type NHCBParser struct {
|
||||||
// State of the parser.
|
// State of the parser.
|
||||||
state collectionState
|
state collectionState
|
||||||
|
|
||||||
|
// Preloaded information about classic histogram series.
|
||||||
|
preload histogramInfoPreloaded
|
||||||
|
|
||||||
// Caches the values from the underlying parser.
|
// Caches the values from the underlying parser.
|
||||||
// For Series and Histogram.
|
// For Series and Histogram.
|
||||||
bytes []byte
|
bytes []byte
|
||||||
|
@ -190,6 +202,11 @@ func (p *NHCBParser) Next() (Entry, error) {
|
||||||
return p.entry, p.err
|
return p.entry, p.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We are advancing the embedded parser, whatever we knew preloaded
|
||||||
|
// about the previous series is now invalid.
|
||||||
|
p.preload.hasName = false
|
||||||
|
p.preload.hasHash = false
|
||||||
|
|
||||||
p.entry, p.err = p.parser.Next()
|
p.entry, p.err = p.parser.Next()
|
||||||
if p.err != nil {
|
if p.err != nil {
|
||||||
if errors.Is(p.err, io.EOF) && p.processNHCB() {
|
if errors.Is(p.err, io.EOF) && p.processNHCB() {
|
||||||
|
@ -237,6 +254,7 @@ func (p *NHCBParser) Next() (Entry, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if labels have changed and we should emit the NHCB.
|
// Return true if labels have changed and we should emit the NHCB.
|
||||||
|
// Also store the calculated metric name and hash if possible for future use.
|
||||||
func (p *NHCBParser) compareLabels() bool {
|
func (p *NHCBParser) compareLabels() bool {
|
||||||
if p.state != stateCollecting {
|
if p.state != stateCollecting {
|
||||||
return false
|
return false
|
||||||
|
@ -245,26 +263,38 @@ func (p *NHCBParser) compareLabels() bool {
|
||||||
// Different metric type.
|
// Different metric type.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
_, name := convertnhcb.GetHistogramMetricBaseName(p.lset.Get(labels.MetricName))
|
p.preload.hasName = true
|
||||||
if p.lastHistogramName != name {
|
p.preload.suffixType, p.preload.metricName = convertnhcb.GetHistogramMetricBaseName(p.lset.Get(labels.MetricName))
|
||||||
|
if p.lastHistogramName != p.preload.metricName {
|
||||||
// Different metric name.
|
// Different metric name.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
nextHash, _ := p.lset.HashWithoutLabels(p.hBuffer, labels.BucketLabel)
|
p.preload.hasHash = true
|
||||||
|
p.preload.hash, _ = p.lset.HashWithoutLabels(p.hBuffer, labels.BucketLabel)
|
||||||
// Different label values.
|
// Different label values.
|
||||||
return p.lastHistogramLabelsHash != nextHash
|
return p.lastHistogramLabelsHash != p.preload.hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the label set of the classic histogram without suffix and bucket `le` label.
|
// Save the label set of the classic histogram without suffix and bucket `le` label.
|
||||||
func (p *NHCBParser) storeClassicLabels(name string) {
|
func (p *NHCBParser) storeClassicLabels(name string) {
|
||||||
p.lastHistogramName = name
|
p.lastHistogramName = name
|
||||||
p.lastHistogramLabelsHash, _ = p.lset.HashWithoutLabels(p.hBuffer, labels.BucketLabel)
|
if p.preload.hasHash {
|
||||||
|
p.lastHistogramLabelsHash = p.preload.hash
|
||||||
|
} else {
|
||||||
|
p.lastHistogramLabelsHash, _ = p.lset.HashWithoutLabels(p.hBuffer, labels.BucketLabel)
|
||||||
|
}
|
||||||
p.lastHistogramExponential = false
|
p.lastHistogramExponential = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *NHCBParser) storeExponentialLabels() {
|
func (p *NHCBParser) storeExponentialLabels() {
|
||||||
p.lastHistogramName = p.lset.Get(labels.MetricName)
|
p.lastHistogramName = p.lset.Get(labels.MetricName)
|
||||||
p.lastHistogramLabelsHash, _ = p.lset.HashWithoutLabels(p.hBuffer)
|
if p.preload.hasHash {
|
||||||
|
p.lastHistogramLabelsHash = p.preload.hash
|
||||||
|
} else {
|
||||||
|
// In the current model and client_golang, "le" label is not allowed
|
||||||
|
// for histogram so ignoring "le" here is ok.
|
||||||
|
p.lastHistogramLabelsHash, _ = p.lset.HashWithoutLabels(p.hBuffer, labels.BucketLabel)
|
||||||
|
}
|
||||||
p.lastHistogramExponential = true
|
p.lastHistogramExponential = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,9 +306,16 @@ func (p *NHCBParser) handleClassicHistogramSeries(lset labels.Labels) bool {
|
||||||
if p.typ != model.MetricTypeHistogram {
|
if p.typ != model.MetricTypeHistogram {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mName := lset.Get(labels.MetricName)
|
|
||||||
|
var name string
|
||||||
|
var suffixType convertnhcb.SuffixType
|
||||||
|
if p.preload.hasName {
|
||||||
|
suffixType, name = p.preload.suffixType, p.preload.metricName
|
||||||
|
} else {
|
||||||
|
suffixType, name = convertnhcb.GetHistogramMetricBaseName(lset.Get(labels.MetricName))
|
||||||
|
}
|
||||||
|
|
||||||
// Sanity check to ensure that the TYPE metadata entry name is the same as the base name.
|
// Sanity check to ensure that the TYPE metadata entry name is the same as the base name.
|
||||||
suffixType, name := convertnhcb.GetHistogramMetricBaseName(mName)
|
|
||||||
if name != string(p.bName) {
|
if name != string(p.bName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue