mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-15 08:23:34 +01:00
lib/promscrape: reduce latency for k8s GetLabels (#2454)
replaces internStringMap with sync.Map - it greatly reduces lock contention concurently reload scrape work for api watcher - each object labels added by dedicated CPU changes can be tested with following script https://gist.github.com/f41gh7/6f8f8d8719786aff1f18a85c23aebf70
This commit is contained in:
parent
9dbfd99777
commit
429848a67d
@ -9,6 +9,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
|
||||||
@ -1221,24 +1222,27 @@ func internLabelStrings(labels []prompbmarshal.Label) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func internString(s string) string {
|
func internString(s string) string {
|
||||||
internStringsMapLock.Lock()
|
if sInterned, ok := internStringsMap.Load(s); ok {
|
||||||
defer internStringsMapLock.Unlock()
|
return sInterned.(string)
|
||||||
|
}
|
||||||
if sInterned, ok := internStringsMap[s]; ok {
|
isc := atomic.LoadUint64(&internStringCount)
|
||||||
return sInterned
|
if isc > 100e3 {
|
||||||
|
internStringsMapLock.Lock()
|
||||||
|
internStringsMap = sync.Map{}
|
||||||
|
atomic.AddUint64(&internStringCount, ^(isc - 1))
|
||||||
|
internStringsMapLock.Unlock()
|
||||||
}
|
}
|
||||||
// Make a new copy for s in order to remove references from possible bigger string s refers to.
|
// Make a new copy for s in order to remove references from possible bigger string s refers to.
|
||||||
sCopy := string(append([]byte{}, s...))
|
sCopy := string(append([]byte{}, s...))
|
||||||
internStringsMap[sCopy] = sCopy
|
internStringsMap.Store(sCopy, sCopy)
|
||||||
if len(internStringsMap) > 100e3 {
|
atomic.AddUint64(&internStringCount, 1)
|
||||||
internStringsMap = make(map[string]string, 100e3)
|
|
||||||
}
|
|
||||||
return sCopy
|
return sCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
internStringCount = uint64(0)
|
||||||
internStringsMapLock sync.Mutex
|
internStringsMapLock sync.Mutex
|
||||||
internStringsMap = make(map[string]string, 100e3)
|
internStringsMap = sync.Map{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func getParamsFromLabels(labels []prompbmarshal.Label, paramsOrig map[string][]string) map[string][]string {
|
func getParamsFromLabels(labels []prompbmarshal.Label, paramsOrig map[string][]string) map[string][]string {
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
|
||||||
"github.com/VictoriaMetrics/metrics"
|
"github.com/VictoriaMetrics/metrics"
|
||||||
@ -522,15 +523,36 @@ func (uw *urlWatcher) reloadScrapeWorksForAPIWatchersLocked(awsMap map[*apiWatch
|
|||||||
for i := range aws {
|
for i := range aws {
|
||||||
swosByKey[i] = make(map[string][]interface{})
|
swosByKey[i] = make(map[string][]interface{})
|
||||||
}
|
}
|
||||||
for key, o := range uw.objectsByKey {
|
// update swos concurrently,
|
||||||
labels := o.getTargetLabels(uw.gw)
|
// it must decrease reload time for high number of records at promscrape file
|
||||||
for i, aw := range aws {
|
maxConcurrent := cgroup.AvailableCPUs() - 2
|
||||||
swos := aw.getScrapeWorkObjectsForLabels(labels)
|
if maxConcurrent < 1 {
|
||||||
if len(swos) > 0 {
|
maxConcurrent = 1
|
||||||
swosByKey[i][key] = swos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
limit := make(chan struct{}, maxConcurrent)
|
||||||
|
var (
|
||||||
|
mu sync.Mutex
|
||||||
|
wg sync.WaitGroup
|
||||||
|
)
|
||||||
|
for key, o := range uw.objectsByKey {
|
||||||
|
limit <- struct{}{}
|
||||||
|
wg.Add(1)
|
||||||
|
// update swsos for each target at separate CPU
|
||||||
|
go func(key string, o object) {
|
||||||
|
labels := o.getTargetLabels(uw.gw)
|
||||||
|
for i, aw := range aws {
|
||||||
|
swos := aw.getScrapeWorkObjectsForLabels(labels)
|
||||||
|
if len(swos) > 0 {
|
||||||
|
mu.Lock()
|
||||||
|
swosByKey[i][key] = swos
|
||||||
|
mu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
<-limit
|
||||||
|
}(key, o)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
for i, aw := range aws {
|
for i, aw := range aws {
|
||||||
aw.reloadScrapeWorks(uw, swosByKey[i])
|
aw.reloadScrapeWorks(uw, swosByKey[i])
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user