github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/state/stategen/hot_state_cache.go (about)

     1  package stategen
     2  
     3  import (
     4  	"sync"
     5  
     6  	lru "github.com/hashicorp/golang-lru"
     7  	"github.com/prometheus/client_golang/prometheus"
     8  	"github.com/prometheus/client_golang/prometheus/promauto"
     9  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    10  )
    11  
    12  var (
    13  	// hotStateCacheSize defines the max number of hot state this can cache.
    14  	hotStateCacheSize = 32
    15  	// Metrics
    16  	hotStateCacheHit = promauto.NewCounter(prometheus.CounterOpts{
    17  		Name: "hot_state_cache_hit",
    18  		Help: "The total number of cache hits on the hot state cache.",
    19  	})
    20  	hotStateCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
    21  		Name: "hot_state_cache_miss",
    22  		Help: "The total number of cache misses on the hot state cache.",
    23  	})
    24  )
    25  
    26  // hotStateCache is used to store the processed beacon state after finalized check point..
    27  type hotStateCache struct {
    28  	cache *lru.Cache
    29  	lock  sync.RWMutex
    30  }
    31  
    32  // newHotStateCache initializes the map and underlying cache.
    33  func newHotStateCache() *hotStateCache {
    34  	cache, err := lru.New(hotStateCacheSize)
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  	return &hotStateCache{
    39  		cache: cache,
    40  	}
    41  }
    42  
    43  // Get returns a cached response via input block root, if any.
    44  // The response is copied by default.
    45  func (c *hotStateCache) get(root [32]byte) iface.BeaconState {
    46  	c.lock.RLock()
    47  	defer c.lock.RUnlock()
    48  	item, exists := c.cache.Get(root)
    49  
    50  	if exists && item != nil {
    51  		hotStateCacheHit.Inc()
    52  		return item.(iface.BeaconState).Copy()
    53  	}
    54  	hotStateCacheMiss.Inc()
    55  	return nil
    56  }
    57  
    58  // GetWithoutCopy returns a non-copied cached response via input block root.
    59  func (c *hotStateCache) getWithoutCopy(root [32]byte) iface.BeaconState {
    60  	c.lock.RLock()
    61  	defer c.lock.RUnlock()
    62  	item, exists := c.cache.Get(root)
    63  	if exists && item != nil {
    64  		hotStateCacheHit.Inc()
    65  		return item.(iface.BeaconState)
    66  	}
    67  	hotStateCacheMiss.Inc()
    68  	return nil
    69  }
    70  
    71  // put the response in the cache.
    72  func (c *hotStateCache) put(root [32]byte, state iface.BeaconState) {
    73  	c.lock.Lock()
    74  	defer c.lock.Unlock()
    75  	c.cache.Add(root, state)
    76  }
    77  
    78  // has returns true if the key exists in the cache.
    79  func (c *hotStateCache) has(root [32]byte) bool {
    80  	c.lock.RLock()
    81  	defer c.lock.RUnlock()
    82  	return c.cache.Contains(root)
    83  }
    84  
    85  // delete deletes the key exists in the cache.
    86  func (c *hotStateCache) delete(root [32]byte) bool {
    87  	c.lock.Lock()
    88  	defer c.lock.Unlock()
    89  	return c.cache.Remove(root)
    90  }