2020-12-17 20:40:47 +00:00
|
|
|
package stategen
|
2020-03-04 22:09:21 +00:00
|
|
|
|
|
|
|
import (
|
2020-06-23 22:06:47 +00:00
|
|
|
"sync"
|
|
|
|
|
2020-03-04 22:09:21 +00:00
|
|
|
lru "github.com/hashicorp/golang-lru"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
2023-03-17 18:52:56 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
|
|
|
lruwrpr "github.com/prysmaticlabs/prysm/v4/cache/lru"
|
2020-03-04 22:09:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// hotStateCacheSize defines the max number of hot state this can cache.
|
2020-09-24 18:10:02 +00:00
|
|
|
hotStateCacheSize = 32
|
2020-03-04 22:09:21 +00:00
|
|
|
// Metrics
|
|
|
|
hotStateCacheHit = promauto.NewCounter(prometheus.CounterOpts{
|
|
|
|
Name: "hot_state_cache_hit",
|
|
|
|
Help: "The total number of cache hits on the hot state cache.",
|
|
|
|
})
|
|
|
|
hotStateCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
|
|
|
|
Name: "hot_state_cache_miss",
|
|
|
|
Help: "The total number of cache misses on the hot state cache.",
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
2022-05-09 22:25:47 +00:00
|
|
|
// hotStateCache is used to store the processed beacon state after finalized check point.
|
2020-12-17 20:40:47 +00:00
|
|
|
type hotStateCache struct {
|
2020-03-04 22:09:21 +00:00
|
|
|
cache *lru.Cache
|
2020-06-23 22:06:47 +00:00
|
|
|
lock sync.RWMutex
|
2020-03-04 22:09:21 +00:00
|
|
|
}
|
|
|
|
|
2020-12-17 20:40:47 +00:00
|
|
|
// newHotStateCache initializes the map and underlying cache.
|
|
|
|
func newHotStateCache() *hotStateCache {
|
|
|
|
return &hotStateCache{
|
2021-09-02 10:36:54 +00:00
|
|
|
cache: lruwrpr.New(hotStateCacheSize),
|
2020-03-04 22:09:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get returns a cached response via input block root, if any.
|
|
|
|
// The response is copied by default.
|
2022-05-09 22:25:47 +00:00
|
|
|
func (c *hotStateCache) get(blockRoot [32]byte) state.BeaconState {
|
2020-06-23 22:06:47 +00:00
|
|
|
c.lock.RLock()
|
|
|
|
defer c.lock.RUnlock()
|
2022-05-09 22:25:47 +00:00
|
|
|
item, exists := c.cache.Get(blockRoot)
|
2020-03-04 22:09:21 +00:00
|
|
|
|
|
|
|
if exists && item != nil {
|
|
|
|
hotStateCacheHit.Inc()
|
2021-07-23 16:11:21 +00:00
|
|
|
return item.(state.BeaconState).Copy()
|
2020-03-04 22:09:21 +00:00
|
|
|
}
|
|
|
|
hotStateCacheMiss.Inc()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-05-09 22:25:47 +00:00
|
|
|
func (c *hotStateCache) ByBlockRoot(r [32]byte) (state.BeaconState, error) {
|
|
|
|
st := c.get(r)
|
2022-03-09 19:33:18 +00:00
|
|
|
if st == nil {
|
|
|
|
return nil, ErrNotInCache
|
|
|
|
}
|
|
|
|
return st, nil
|
|
|
|
}
|
|
|
|
|
2020-05-08 19:02:48 +00:00
|
|
|
// GetWithoutCopy returns a non-copied cached response via input block root.
|
2022-05-09 22:25:47 +00:00
|
|
|
func (c *hotStateCache) getWithoutCopy(blockRoot [32]byte) state.BeaconState {
|
2020-06-23 22:06:47 +00:00
|
|
|
c.lock.RLock()
|
|
|
|
defer c.lock.RUnlock()
|
2022-05-09 22:25:47 +00:00
|
|
|
item, exists := c.cache.Get(blockRoot)
|
2020-05-08 19:02:48 +00:00
|
|
|
if exists && item != nil {
|
|
|
|
hotStateCacheHit.Inc()
|
2021-07-23 16:11:21 +00:00
|
|
|
return item.(state.BeaconState)
|
2020-05-08 19:02:48 +00:00
|
|
|
}
|
|
|
|
hotStateCacheMiss.Inc()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-12-17 20:40:47 +00:00
|
|
|
// put the response in the cache.
|
2022-05-09 22:25:47 +00:00
|
|
|
func (c *hotStateCache) put(blockRoot [32]byte, state state.BeaconState) {
|
2020-06-23 22:06:47 +00:00
|
|
|
c.lock.Lock()
|
|
|
|
defer c.lock.Unlock()
|
2022-05-09 22:25:47 +00:00
|
|
|
c.cache.Add(blockRoot, state)
|
2020-03-04 22:09:21 +00:00
|
|
|
}
|
|
|
|
|
2020-12-17 20:40:47 +00:00
|
|
|
// has returns true if the key exists in the cache.
|
2022-05-09 22:25:47 +00:00
|
|
|
func (c *hotStateCache) has(blockRoot [32]byte) bool {
|
2020-06-23 22:06:47 +00:00
|
|
|
c.lock.RLock()
|
|
|
|
defer c.lock.RUnlock()
|
2022-05-09 22:25:47 +00:00
|
|
|
return c.cache.Contains(blockRoot)
|
2020-03-04 22:09:21 +00:00
|
|
|
}
|
2020-05-08 19:02:48 +00:00
|
|
|
|
2020-12-17 20:40:47 +00:00
|
|
|
// delete deletes the key exists in the cache.
|
2022-05-09 22:25:47 +00:00
|
|
|
func (c *hotStateCache) delete(blockRoot [32]byte) bool {
|
2020-06-23 22:06:47 +00:00
|
|
|
c.lock.Lock()
|
|
|
|
defer c.lock.Unlock()
|
2022-05-09 22:25:47 +00:00
|
|
|
return c.cache.Remove(blockRoot)
|
2020-05-08 19:02:48 +00:00
|
|
|
}
|