LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_progcache_user.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 5 17 29.4 %
Date: 2026-03-31 06:22:16 Functions: 1 120 0.8 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_progcache_fd_progcache_user_h
       2             : #define HEADER_fd_src_flamenco_progcache_fd_progcache_user_h
       3             : 
       4             : /* fd_progcache_user.h provides an API for managing a cache of loaded
       5             :    Solana on-chain program.
       6             : 
       7             :    ### Background
       8             : 
       9             :    Solana on-chain programs are rarely updated but frequently executed.
      10             :    Before a program can be executed, it must be loaded and verified,
      11             :    which is costly.
      12             : 
      13             :    ### Fork management
      14             : 
      15             :    The program cache is fork-aware (using funk transactions).  Txn-level
      16             :    operations take an exclusive lock over the cache (record ops are
      17             :    stalled indefinitely until the txn completes).
      18             : 
      19             :    ### Cache entry
      20             : 
      21             :    Each Solana program can have a number of program cache entries
      22             :    (typically only zero or one, in rare cases where the program content
      23             :    differs across forks multiple).
      24             : 
      25             :    A cache entry consists of a funk_rec object (from a preallocated
      26             :    object pool), and a variable-sized fd_progcache_entry struct
      27             :    (from an fd_alloc heap).
      28             : 
      29             :    ### Cache fill policy
      30             : 
      31             :    fd_progcache is lazily filled on reads, and eagerly invalidated
      32             :    if underlying programs are written to.
      33             : 
      34             :    ### Cache evict policy
      35             : 
      36             :    Cache eviction (i.e. force removal of potentially useful records)
      37             :    happens on fill.  Specifically, cache eviction is triggered when a
      38             :    cache fill fails to allocate from the wksp (fd_alloc) heap.
      39             : 
      40             :    fd_progcache further has a concept of "generations" (gen).  Each
      41             :    cache fill operation specifies a 'gen' number.  Only entries with a
      42             :    lower 'gen' number may get evicted.
      43             : 
      44             :    ### Garbage collect policy
      45             : 
      46             :    fd_progcache cleans up unused entries eagerly when:
      47             : 
      48             :    1. a database fork is cancelled (e.g. slot is rooted and competing
      49             :       history dies, or consensus layer prunes a fork)
      50             :    2. a cache entry is orphaned (updated or invalidated by an epoch
      51             :       boundary) */
      52             : 
      53             : #include "fd_progcache.h"
      54             : #include "fd_prog_load.h"
      55             : #include "../runtime/fd_runtime_const.h"
      56             : 
      57             : struct fd_progcache_metrics {
      58             :   ulong lookup_cnt;
      59             :   ulong hit_cnt;
      60             :   ulong miss_cnt;
      61             :   ulong oom_heap_cnt;
      62             :   ulong oom_desc_cnt;
      63             :   ulong fill_cnt;
      64             :   ulong fill_tot_sz;
      65             :   ulong spill_cnt;
      66             :   ulong spill_tot_sz;
      67             :   ulong evict_cnt;
      68             :   ulong evict_tot_sz;
      69             :   ulong cum_pull_ticks;
      70             :   ulong cum_load_ticks;
      71             : };
      72             : 
      73             : typedef struct fd_progcache_metrics fd_progcache_metrics_t;
      74             : 
      75             : /* fd_progcache_t is a thread-local client to a program cache funk
      76             :    instance.  This struct is quite large and therefore not local/stack
      77             :    declaration-friendly. */
      78             : 
      79             : struct fd_progcache {
      80             :   fd_progcache_join_t join[1];
      81             :   fd_accdb_lineage_t  lineage[1];
      82             : 
      83             :   fd_progcache_metrics_t * metrics;
      84             : 
      85             :   uchar * scratch;
      86             :   ulong   scratch_sz;
      87             : 
      88             :   uint spill_active;
      89             : };
      90             : 
      91             : FD_PROTOTYPES_BEGIN
      92             : 
      93             : extern FD_TL fd_progcache_metrics_t fd_progcache_metrics_default;
      94             : 
      95             : /* Constructor */
      96             : 
      97             : static inline ulong
      98           0 : fd_progcache_align( void ) {
      99           0 :   return alignof(fd_progcache_t);
     100           0 : }
     101             : 
     102             : static inline ulong
     103           0 : fd_progcache_footprint( void ) {
     104           0 :   return sizeof(fd_progcache_t);
     105           0 : }
     106             : 
     107             : static inline fd_progcache_t *
     108           0 : fd_progcache_new( void * ljoin ) {
     109           0 :   return ljoin;
     110           0 : }
     111             : 
     112             : static inline void *
     113           0 : fd_progcache_delete( void * ljoin ) {
     114           0 :   return ljoin;
     115           0 : }
     116             : 
     117             : /* fd_progcache_join joins the caller to a program cache shmem instance.
     118             :    scratch points to a FD_PROGCACHE_SCRATCH_ALIGN aligned scratch buffer
     119             :    and scratch_sz is the size of the largest program/ELF binary that is
     120             :    going to be loaded (typically max account data sz). */
     121             : 
     122             : fd_progcache_t *
     123             : fd_progcache_join( fd_progcache_t *       ljoin,
     124             :                    fd_progcache_shmem_t * shmem,
     125             :                    uchar *                scratch,
     126             :                    ulong                  scratch_sz );
     127             : 
     128          99 : #define FD_PROGCACHE_SCRATCH_ALIGN     (64UL)
     129          99 : #define FD_PROGCACHE_SCRATCH_FOOTPRINT FD_RUNTIME_ACC_SZ_MAX
     130             : 
     131             : /* fd_progcache_leave detaches the caller from a program cache. */
     132             : 
     133             : void *
     134             : fd_progcache_leave( fd_progcache_t *        cache,
     135             :                     fd_progcache_shmem_t ** opt_shmem );
     136             : 
     137             : /* fd_progcache_revision_slot returns the slot number under which a
     138             :    progcache entry is indexed at.  epoch_slot0 is the first slot number
     139             :    of the epoch.  deploy_slot is the slot at which the program was
     140             :    deployed using the program loader. */
     141             : 
     142             : static inline ulong
     143             : fd_progcache_revision_slot( ulong epoch_slot0,
     144         165 :                             ulong deploy_slot ) {
     145         165 :   return fd_ulong_max( epoch_slot0, deploy_slot );
     146         165 : }
     147             : 
     148             : /* fd_progcache_peek queries the program cache for an existing cache
     149             :    entry.  Does not fill the cache.  Returns a pointer to the entry on
     150             :    cache hit.  Returns NULL on cache miss.  It is the caller's
     151             :    responsibility to release the returned record with
     152             :    fd_progcache_rec_close. */
     153             : 
     154             : fd_progcache_rec_t * /* read locked */
     155             : fd_progcache_peek( fd_progcache_t    * cache,
     156             :                    fd_xid_t    const * xid,
     157             :                    fd_pubkey_t const * prog_addr,
     158             :                    ulong               revision_slot );
     159             : 
     160             : /* fd_progcache_pull loads a program from cache, filling the cache if
     161             :    necessary.  The load operation can have a number of outcomes:
     162             :    - Returns a pointer to an existing cache entry (cache hit, state
     163             :      either "Loaded" or "FailedVerification")
     164             :    - Returns a pointer to a newly created cache entry (cache fill,
     165             :      state either "Loaded" or "FailedVerification")
     166             :    - Returns NULL if the requested program account is not deployed (i.e.
     167             :      account is missing, the program is under visibility delay, or user
     168             :      has not finished uploading the program)
     169             :    In other words, this method guarantees to return a cache entry if a
     170             :    deployed program was found in the account database, and the program
     171             :    either loaded successfully, or failed ELF/bytecode verification.
     172             :    It is the caller's responsibility to release the returned record with
     173             :    fd_progcache_rec_close. */
     174             : 
     175             : fd_progcache_rec_t * /* read locked */
     176             : fd_progcache_pull( fd_progcache_t           * cache,
     177             :                    fd_xid_t const           * xid,
     178             :                    fd_pubkey_t        const * prog_addr,
     179             :                    fd_prog_load_env_t const * env,
     180             :                    fd_accdb_ro_t            * progdata_ro,
     181             :                    fd_pubkey_t        const * program_owner );
     182             : 
     183             : /* fd_progcache_rec_close releases a cache record handle returned by
     184             :    fd_progcache_{pull,peek}. */
     185             : 
     186             : void
     187             : fd_progcache_rec_close( fd_progcache_t *     cache,
     188             :                         fd_progcache_rec_t * rec );
     189             : 
     190             : FD_PROTOTYPES_END
     191             : 
     192             : #endif /* HEADER_fd_src_flamenco_progcache_fd_progcache_user_h */

Generated by: LCOV version 1.14