package octez-proto-libs
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=c6df840ebbf115e454db949028c595bec558a59a66cade73b52a6d099d6fa4d4
sha512=d8aee903b9fe130d73176bc8ec38b78c9ff65317da3cb4f3415f09af0c625b4384e7498201fdb61aa39086a7d5d409d0ab3423f9bc3ab989a680cf444a79bc13
doc/octez-proto-libs.protocol-environment/Tezos_protocol_environment/Internal_for_tests/Environment_cache/index.html
Module Internal_for_tests.Environment_cacheSource
An LRU inter-blocks cache for the economic protocol
This is for use *within* the Environment_context only.
Frequently used data should be kept in memory and persist along a chain of blocks. The caching mechanism allows the economic protocol to declare such data and to rely on an Least Recently Used strategy to keep the cache size under a fixed limit.
One important difficulty is to correctly maintain this in-memory cache. There are three issues related to this mechanism from the shell perspective:
1. The in-memory cache must take chain reorganization into account. (Chain reorganizations occur when the node's preferred chain is not the one that has been chosen by the consensus algorithm.)
2. The in-memory cache must be completely determined by the storage.
3. The loading of the cache should introduce minimal latency during node reboots, RPC processing, or other operations. The cache should also have similar reactivity time on every node, independently of the fact that the node has just been rebooted or not.
This module implements the core logic of the cache mechanism (not the storage) part. The implementation provided to the protocol is implemented in Environment_context.Cache.
The type of a cache is parameterized by the type of the values stored.
When a value is cached, we also stored metadata about the status of this value in the cache. The value's key and its metadata are the only data stored in the context. The set of all the keys and metadatas of the cache is called the *domain*.
The actual cached values are introduced at runtime during cache lifetime. When the node needs to load a cache in memory for a specific context, it uses a *builder*, i.e., a function which reconstructs a cached value from a key. We can reconstruct all the values in a cache given its domain. In practice, such builder is provided by the cache mechanism client, i.e., the economic protocol.
Finally, notice that the cache is divided into sub-caches which have their own size limit. Each sub-cache is referenced by an index (as a positive integer). This layout is defined by the economic protocol.
Abstract type for a cache parameterized by the value type.
Cache layout
A layout determines the number of sub-caches as well as the size limit of those sub-caches. No assumption is made on the unit of each of those sub-cache sizes. All we use is the natural ordering of int. In particular, the size units for different sub-caches need not be the same.
There are only two constructors for a cache:
uninitialisedwhich returns an uninitialised cache ;
from_layoutwhich initialises a cache with a layout.
Moreover, the layout of the cache cannot be resized. This way, the cache's layout is determined uniquely by the one given to from_layout.
The only way to change the layout of a cache is to create a new cache and explicitly copy all the values from the previous cache to the new one. Such constraint may be relaxed in the future if necessary.
Size of sub-caches or values.
Index of the subcache in the cache. Values of this type should stay between 0 and 16383.
uninitialised is a special value which identify cache without a layout. Most functions of this interface will raise Invalid_argument is they are called on this value.
from_layout layout initializes a cache with the layout. Such function is intended to be called by the init function of the economic protocol. In particular, this means that the cache's values will be reset after stitching of context.
compatible_layout cache layout returns true if the layout is compatible with the one cache was initialised with, false otherwise. By compatible, we mean that the layouts are actually precisely the same.
clear cache resets the cache except the layout. It is equivalent to from_layout layout where layout was the layout provided to initialise the cache.
Keys
A key is built from an identifier and an index of the corresponding cache.
Abstract type for a cache key.
Identifier of a key.
key_of_identifier ~cache_index identifier builds a key from the cache_index and the identifier.
No checks are made to ensure the validity of the index.
identifier_of_key key returns the identifier associated to the key.
type value_metadata = {size : int;(*
*)sizemust be strictly positive. This attribute is used to computed the cache size. The unit of the size is not specified at this stage. It is up to the economic protocol to give a measure of it.birth : int64;(*
*)birthmust be greater than 1. This number corresponds to the number of entries inserted in the cache after the insertion of this entry. Thebirthis used to determine which entry is the oldest one. The risk of overflow is minor.cache_nonce : Tezos_base.TzPervasives.Bytes.t;(*cache_nonceidentifies the block that introduced this cache entry. The nonce must uniquely identify the block which modifies this value. It cannot be the block hash for circularity reasons: The value of the nonce is stored onto the context and consequently influences the context hash of the very same block. Such nonce cannot be determined by the shell and its computation is delegated to the economic protocol.
*)cache_nonces are used by the shell to properly relate the cached entries with the current block and its predecessors. In particular in case of reorganizations, that is a context which is not on the same branch as the current branch,cache_nonces are used to filter out entries that do not exist in the target branch.
}Metadata associated to a value in the cache.
Cache Getters/Setters
find cache key is Some v if key has an associated cached value v in cache, or None otherwise.
lookup cache key is Some (v, m) where v is the value associated to key and m is the corresponding metadata. This function returns None if key is not in the cache domain.
update cache key request returns a new version of cache where a requested change has been applied to the key.
More specifically:
update cache key Noneremoveskeyfrom thecache.
update cache key (Some (value, size))iscachewherekeyis now associated tovalue.
The metadata of the key is also updated in the returned cache:
- the
sizefield is modified in the metadata ; - the
birthis the higher birth, so that the key is the most recently used key.
The cache_nonce of the entry is preserved.
If the cache is full, the insertion of a new entry provokes the removal of the least recently used entries.
future_cache_expectation cache ~time_in_blocks returns a predicted cache that tries to anticipate the state of cache in time_in_blocks. This function is using an heuristic.
Cache synchronisation
Synchronisation of a cache aims to be done once all the accesses to the caches have been done by the economic protocol.
For each value added or updated since the last synchronisation, they are updated with the nonce provided by the economic protocol.
The domain is the on-disk representation of the cache. Notice that in-memory values must be constructed from a domain to get a cache.
empty_domain d returns true iff d is the domain of an uninitialized cache.
val from_cache :
'value t ->
domain ->
value_of_key:(key -> ('value, 'trace) result Lwt.t) ->
('value t, 'trace) result Lwt.tfrom_cache initial domain ~value_of_key initializes a cache with the given domain by reusing values from initial if nonces match, or by calling value_of_key otherwise.
domain and initial must share the same layout.
This function is typically used when the cache is loaded from the context. See Environment_context.
sync cache ~cache_nonce computes a new cache with a new domain.
Various functions used to introspect the content of the cache.
number_of_caches cache returns the number of sub-caches in the cache.
cache_size cache ~cache_index returns an overapproximation of the size of the cache. Returns None if cache_index is an invalid index.
cache_size_limit cache ~cache_index returns the maximal size of the cache indexed by cache_index. Returns None if cache_index is an invalid index.
list_keys cache ~cache_index returns the list of keys along with their size recorded into the subcache with index cache_index.
key_rank cache key returns the rank of the value associated to the given key. The rank is defined as the number of values older than the current one. Returns None if the key is not in the cache.
pp fmt cache is a pretty printer for a cache.