@@ -43,13 +43,13 @@ var separatorByteSlice = []byte{model.SeparatorByte} // For convenient use with
4343// Use CachedTGatherer with classic Registry using NewMultiTRegistry and ToTransactionalGatherer helpers.
4444// NOTE(bwplotka): Experimental, API and behaviour can change.
4545type CachedTGatherer struct {
46- metricFamilyByName map [string ]* family
47- mMu sync.RWMutex
46+ metricFamiliesByName map [string ]* family
47+ mMu sync.RWMutex
4848}
4949
5050func NewCachedTGatherer () * CachedTGatherer {
5151 return & CachedTGatherer {
52- metricFamilyByName : map [string ]* family {},
52+ metricFamiliesByName : map [string ]* family {},
5353 }
5454}
5555
@@ -69,6 +69,7 @@ type metric struct {
6969// MetricFamilies pruned and the remaining MetricFamilies sorted by name within
7070// the slice, with the contained Metrics sorted within each MetricFamily.
7171func normalizeMetricFamilies (metricFamiliesByName map [string ]* family ) []* dto.MetricFamily {
72+ // TODO(bwplotka): We could optimize this further by bookkeeping this slice in place.
7273 for _ , mf := range metricFamiliesByName {
7374 if cap (mf .Metric ) < len (mf .metricsByHash ) {
7475 mf .Metric = make ([]* dto.Metric , 0 , len (mf .metricsByHash ))
@@ -80,9 +81,6 @@ func normalizeMetricFamilies(metricFamiliesByName map[string]*family) []*dto.Met
8081 sort .Sort (internal .MetricSorter (mf .Metric ))
8182 }
8283
83- for _ , mf := range metricFamiliesByName {
84- sort .Sort (internal .MetricSorter (mf .Metric ))
85- }
8684 names := make ([]string , 0 , len (metricFamiliesByName ))
8785 for name , mf := range metricFamiliesByName {
8886 if len (mf .Metric ) > 0 {
@@ -102,8 +100,8 @@ func (c *CachedTGatherer) Gather() (_ []*dto.MetricFamily, done func(), err erro
102100 c .mMu .RLock ()
103101
104102 // BenchmarkCachedTGatherer_Update shows, even for 1 million metrics among 1000 families
105- // this is efficient enough (~300µs and ~50 kB per op), no need to cache it for now.
106- return normalizeMetricFamilies (c .metricFamilyByName ), c .mMu .RUnlock , nil
103+ // this is efficient enough (~400ms and ~50 kB per op), no need to cache it for now.
104+ return normalizeMetricFamilies (c .metricFamiliesByName ), c .mMu .RUnlock , nil
107105}
108106
109107type Key struct {
@@ -174,7 +172,7 @@ func (c *CachedTGatherer) Update(reset bool, inserts []Insert, deletions []Key)
174172 }
175173
176174 // Update metric family.
177- mf , ok := c .metricFamilyByName [inserts [i ].FQName ]
175+ mf , ok := c .metricFamiliesByName [inserts [i ].FQName ]
178176 if ! ok {
179177 mf = & family {
180178 MetricFamily : & dto.MetricFamily {},
@@ -186,7 +184,7 @@ func (c *CachedTGatherer) Update(reset bool, inserts []Insert, deletions []Key)
186184 mf .Type = inserts [i ].ValueType .ToDTO ()
187185 mf .Help = & inserts [i ].Help
188186
189- c .metricFamilyByName [inserts [i ].FQName ] = mf
187+ c .metricFamiliesByName [inserts [i ].FQName ] = mf
190188
191189 // Update metric pointer.
192190 hSum := inserts [i ].hash ()
@@ -250,7 +248,7 @@ func (c *CachedTGatherer) Update(reset bool, inserts []Insert, deletions []Key)
250248 continue
251249 }
252250
253- mf , ok := c .metricFamilyByName [del .FQName ]
251+ mf , ok := c .metricFamiliesByName [del .FQName ]
254252 if ! ok {
255253 continue
256254 }
@@ -261,17 +259,18 @@ func (c *CachedTGatherer) Update(reset bool, inserts []Insert, deletions []Key)
261259 }
262260
263261 if len (mf .metricsByHash ) == 1 {
264- delete (c .metricFamilyByName , del .FQName )
262+ delete (c .metricFamiliesByName , del .FQName )
265263 continue
266264 }
267265
268266 delete (mf .metricsByHash , hSum )
269267 }
270268
271269 if reset {
272- for name , mf := range c .metricFamilyByName {
270+ // Trading off-time instead of memory allocated for otherwise needed replacement map.
271+ for name , mf := range c .metricFamiliesByName {
273272 if ! mf .touched {
274- delete (c .metricFamilyByName , name )
273+ delete (c .metricFamiliesByName , name )
275274 continue
276275 }
277276 for hash , m := range mf .metricsByHash {
@@ -281,12 +280,14 @@ func (c *CachedTGatherer) Update(reset bool, inserts []Insert, deletions []Key)
281280 }
282281 }
283282 if len (mf .metricsByHash ) == 0 {
284- delete (c .metricFamilyByName , name )
283+ delete (c .metricFamiliesByName , name )
285284 }
286285 }
287286 }
288287
289- for _ , mf := range c .metricFamilyByName {
288+ // TODO(bwplotka): Potentially move this only for reset, but then code would assume
289+ // you either only update or only reset update. For now we can live with small overhead.
290+ for _ , mf := range c .metricFamiliesByName {
290291 mf .touched = false
291292 for _ , m := range mf .metricsByHash {
292293 m .touched = false
0 commit comments