Skip to content

Commit

Permalink
Change metrics store to use sync.Map
Browse files Browse the repository at this point in the history
The cache map for metrics cannot be concurrently accessed in the current version. This caused a problem that heavy metrics writing to the map will cause a contention with reading, and can potentially cause Prometheus scrape call to timeout. Using sync.Map can remove the mutex.
  • Loading branch information
zhengl7 authored and Zheng Li committed Jan 17, 2020
1 parent e463aed commit 620c817
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 19 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/prometheus/prometheus v2.5.0+incompatible
github.com/robfig/cron/v3 v3.0.0
github.com/spf13/pflag v1.0.5
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72
golang.org/x/tools v0.0.0-20200117212325-1486df0b2558
k8s.io/api v0.0.0-20191112020540-7f9008e52f64
k8s.io/apimachinery v0.0.0-20191111054156-6eb29fdf75dc
k8s.io/autoscaler/vertical-pod-autoscaler v0.0.0-20191115143342-4cf961056038
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand All @@ -245,6 +247,7 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -312,7 +315,10 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117212325-1486df0b2558 h1:x+gbgIDM9JY+y1GXH+Q+/YaYETOliNiANkCuJ/Ts/P4=
golang.org/x/tools v0.0.0-20200117212325-1486df0b2558/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
Expand Down
30 changes: 12 additions & 18 deletions pkg/metrics_store/metrics_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"sync"

"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types"
)

// FamilyByteSlicer represents a metric family that can be converted to its string
Expand All @@ -40,7 +39,7 @@ type MetricsStore struct {
// metric families, containing a slice of metrics. We need to keep metrics
// grouped by metric families in order to zip families with their help text in
// MetricsStore.WriteAll().
metrics map[types.UID][][]byte
metrics sync.Map
// headers contains the header (TYPE and HELP) of each metric family. It is
// later on zipped with with their corresponding metric families in
// MetricStore.WriteAll().
Expand All @@ -56,7 +55,7 @@ func NewMetricsStore(headers []string, generateFunc func(interface{}) []FamilyBy
return &MetricsStore{
generateMetricsFunc: generateFunc,
headers: headers,
metrics: map[types.UID][][]byte{},
metrics: sync.Map{},
}
}

Expand All @@ -70,18 +69,14 @@ func (s *MetricsStore) Add(obj interface{}) error {
return err
}

s.mutex.Lock()
defer s.mutex.Unlock()

families := s.generateMetricsFunc(obj)
familyStrings := make([][]byte, len(families))

for i, f := range families {
familyStrings[i] = f.ByteSlice()
}

s.metrics[o.GetUID()] = familyStrings

s.metrics.Store(o.GetUID(), familyStrings)
return nil
}

Expand All @@ -99,10 +94,7 @@ func (s *MetricsStore) Delete(obj interface{}) error {
return err
}

s.mutex.Lock()
defer s.mutex.Unlock()

delete(s.metrics, o.GetUID())
s.metrics.Delete(o.GetUID())

return nil
}
Expand Down Expand Up @@ -130,9 +122,7 @@ func (s *MetricsStore) GetByKey(key string) (item interface{}, exists bool, err
// Replace will delete the contents of the store, using instead the
// given list.
func (s *MetricsStore) Replace(list []interface{}, _ string) error {
s.mutex.Lock()
s.metrics = map[types.UID][][]byte{}
s.mutex.Unlock()
s.metrics = sync.Map{}

for _, o := range list {
err := s.Add(o)
Expand All @@ -158,8 +148,12 @@ func (s *MetricsStore) WriteAll(w io.Writer) {
for i, help := range s.headers {
w.Write([]byte(help))
w.Write([]byte{'\n'})
for _, metricFamilies := range s.metrics {
w.Write(metricFamilies[i])
}

s.metrics.Range(func(key interface{}, value interface{}) bool {
metricFamilies := value.([][]byte)
w.Write([]byte(metricFamilies[i]))
w.Write([]byte(metricFamilies[i]))
return true
})
}
}

0 comments on commit 620c817

Please sign in to comment.