-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Receivers|Store: cache matchers for series calls
We have tried caching matchers before with a time-based expiration cache, this time we are trying with LRU cache. We saw some of our receivers busy with compiling regexes and with high CPU usage, similar to the profile of the benchmark I added here: * Adding matcher cache for method `MatchersToPromMatchers` and a new version which uses the cache. * The main change is in `matchesExternalLabels` function which now receives a cache instance. adding matcher cache and refactor matchers Co-authored-by: Andre Branchizio <andre.branchizio@shopify.com> Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com> Using the cache in proxy and tsdb stores (only receiver) Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com> fixing problem with deep equality Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com> adding some docs Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com> Adding benchmark Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com> undo unecessary changes Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com> Adjusting metric names Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com>
- Loading branch information
1 parent
2d738f0
commit a58508d
Showing
8 changed files
with
313 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Copyright (c) The Thanos Authors. | ||
// Licensed under the Apache License 2.0. | ||
|
||
package storepb | ||
|
||
import ( | ||
lru "github.com/hashicorp/golang-lru/v2" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/client_golang/prometheus/promauto" | ||
"github.com/prometheus/prometheus/model/labels" | ||
) | ||
|
||
const DefaultCacheSize = 200 | ||
|
||
type NewItemFunc func(matcher LabelMatcher) (*labels.Matcher, error) | ||
|
||
type MatchersCache struct { | ||
reg prometheus.Registerer | ||
cache *lru.TwoQueueCache[LabelMatcher, *labels.Matcher] | ||
metrics *matcherCacheMetrics | ||
size int | ||
} | ||
|
||
type MatcherCacheOption func(*MatchersCache) | ||
|
||
func WithPromRegistry(reg prometheus.Registerer) MatcherCacheOption { | ||
return func(c *MatchersCache) { | ||
c.reg = reg | ||
} | ||
} | ||
|
||
func WithSize(size int) MatcherCacheOption { | ||
return func(c *MatchersCache) { | ||
c.size = size | ||
} | ||
} | ||
|
||
func NewMatchersCache(opts ...MatcherCacheOption) *MatchersCache { | ||
cache := &MatchersCache{ | ||
reg: prometheus.NewRegistry(), | ||
size: DefaultCacheSize, | ||
} | ||
|
||
for _, opt := range opts { | ||
opt(cache) | ||
} | ||
cache.metrics = newMatcherCacheMetrics(cache.reg) | ||
|
||
return cache | ||
} | ||
|
||
func (c *MatchersCache) GetOrSet(key LabelMatcher, newItem NewItemFunc) (*labels.Matcher, error) { | ||
if c.cache == nil { | ||
lruCache, err := lru.New2Q[LabelMatcher, *labels.Matcher](c.size) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c.cache = lruCache | ||
} | ||
c.metrics.requestsTotal.Inc() | ||
if item, ok := c.cache.Get(key); ok { | ||
c.metrics.hitsTotal.Inc() | ||
return item, nil | ||
} | ||
|
||
item, err := newItem(key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c.cache.Add(key, item) | ||
c.metrics.numItems.Set(float64(c.cache.Len())) | ||
|
||
return item, nil | ||
} | ||
|
||
type matcherCacheMetrics struct { | ||
requestsTotal prometheus.Counter | ||
hitsTotal prometheus.Counter | ||
numItems prometheus.Gauge | ||
} | ||
|
||
func newMatcherCacheMetrics(reg prometheus.Registerer) *matcherCacheMetrics { | ||
return &matcherCacheMetrics{ | ||
requestsTotal: promauto.With(reg).NewCounter(prometheus.CounterOpts{ | ||
Name: "thanos_matchers_cache_requests_total", | ||
Help: "Total number of cache requests for series matchers", | ||
}), | ||
hitsTotal: promauto.With(reg).NewCounter(prometheus.CounterOpts{ | ||
Name: "thanos_matchers_cache_hits_total", | ||
Help: "Total number of cache hits for series matchers", | ||
}), | ||
numItems: promauto.With(reg).NewGauge(prometheus.GaugeOpts{ | ||
Name: "thanos_matchers_cache_items", | ||
Help: "Total number of cached items", | ||
}), | ||
} | ||
} |
Oops, something went wrong.