This repository has been archived by the owner on Aug 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
back schemas and aggs matching with a cache
before this, all regex matching dominated the cpu profile. With this, cpu usage reduced by easily 5x Though we still have: flat cumulative 70ms 0.86% 69.79% 770ms 9.49% github.com/raintank/metrictank/mdata/matchcache.(*Cache).Get due to the map locking We could further optimize this, probably, by changing the idx.AddOrUpdate signature to returning SchemaI and AggI, instead of requiring it as input as @replay suggested. This way we only have to match if it wasn't in the index already. However this requires more intensive changes to the index than I'm comfortable with right now (DefById only has the metricdef, not the properties, we could add them but then we need to adjust how we work with DefById everywhere and do we still need to store the properties in the tree, etc) I rather re-address this when the need is clearer and we have time to give this the attention it deserves.
- Loading branch information
Showing
3 changed files
with
80 additions
and
3 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package matchcache | ||
|
||
import ( | ||
"sync" | ||
"time" | ||
) | ||
|
||
// Cache caches key to uint16 lookups (for schemas and aggregations) | ||
// when it cleans the cache it locks up the entire cache | ||
// this is a tradeoff we can make for simplicity, since this sits on the ingestion | ||
// path, where occasional stalls are ok. | ||
type Cache struct { | ||
sync.Mutex | ||
data map[string]Item | ||
|
||
cleanInterval time.Duration | ||
expireAfter time.Duration | ||
} | ||
|
||
type Item struct { | ||
val uint16 | ||
seen int64 | ||
} | ||
|
||
func New(cleanInterval, expireAfter time.Duration) *Cache { | ||
m := &Cache{ | ||
data: make(map[string]Item), | ||
cleanInterval: cleanInterval, | ||
expireAfter: expireAfter, | ||
} | ||
go m.maintain() | ||
return m | ||
} | ||
|
||
type AddFunc func(key string) uint16 | ||
|
||
// if not in cache, will atomically add it using the provided function | ||
func (m *Cache) Get(key string, fn AddFunc) uint16 { | ||
m.Lock() | ||
item, ok := m.data[key] | ||
if !ok { | ||
item.val = fn(key) | ||
} | ||
item.seen = time.Now().Unix() | ||
m.data[key] = item | ||
m.Unlock() | ||
return item.val | ||
} | ||
|
||
func (m *Cache) maintain() { | ||
ticker := time.NewTicker(m.cleanInterval) | ||
diff := int64(m.expireAfter.Seconds()) | ||
for now := range ticker.C { | ||
nowUnix := now.Unix() | ||
m.Lock() | ||
for key, item := range m.data { | ||
if nowUnix-item.seen > diff { | ||
delete(m.data, key) | ||
} | ||
} | ||
m.Unlock() | ||
} | ||
} |
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