diff --git a/lib/promscrape/targetstatus.go b/lib/promscrape/targetstatus.go index bc8611709e..66288abe90 100644 --- a/lib/promscrape/targetstatus.go +++ b/lib/promscrape/targetstatus.go @@ -16,6 +16,7 @@ import ( "github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime" "github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel" + xxhash "github.com/cespare/xxhash/v2" ) var maxDroppedTargets = flag.Int("promscrape.maxDroppedTargets", 1000, "The maximum number of droppedTargets to show at /api/v1/targets page. "+ @@ -245,7 +246,7 @@ func (st *targetStatus) getDurationFromLastScrape() time.Duration { type droppedTargets struct { mu sync.Mutex - m map[string]droppedTarget + m map[uint64]droppedTarget lastCleanupTime uint64 } @@ -255,7 +256,8 @@ type droppedTarget struct { } func (dt *droppedTargets) Register(originalLabels []prompbmarshal.Label) { - key := promLabelsString(originalLabels) + // It is better to have hash collisions instead of spending additional CPU on promLabelsString() call. + key := labelsHash(originalLabels) currentTime := fasttime.UnixTimestamp() dt.mu.Lock() if k, ok := dt.m[key]; ok { @@ -278,6 +280,24 @@ func (dt *droppedTargets) Register(originalLabels []prompbmarshal.Label) { dt.mu.Unlock() } +func labelsHash(labels []prompbmarshal.Label) uint64 { + d := xxhashPool.Get().(*xxhash.Digest) + for _, label := range labels { + _, _ = d.WriteString(label.Name) + _, _ = d.WriteString(label.Value) + } + h := d.Sum64() + d.Reset() + xxhashPool.Put(d) + return h +} + +var xxhashPool = &sync.Pool{ + New: func() interface{} { + return xxhash.New() + }, +} + // WriteDroppedTargetsJSON writes `droppedTargets` contents to w according to https://prometheus.io/docs/prometheus/latest/querying/api/#targets func (dt *droppedTargets) WriteDroppedTargetsJSON(w io.Writer) { dt.mu.Lock() @@ -311,7 +331,7 @@ func (dt *droppedTargets) WriteDroppedTargetsJSON(w io.Writer) { } var droppedTargetsMap = &droppedTargets{ - m: make(map[string]droppedTarget), + m: make(map[uint64]droppedTarget), } type jobTargetsStatuses struct {