LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_progcache_user.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 2 19 10.5 %
Date: 2026-10-22 18:10:43 Functions: 0 0 -

          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 transactions).  Txn-level
      16             :    operations (attach/publish/cancel) take the fork graph's exclusive
      17             :    lock; a read on the cached lineage never touches it, while switching
      18             :    fork, publishing and the eviction sweep take it shared.
      19             : 
      20             :    ### Cache entry
      21             : 
      22             :    Each Solana program can have a number of program cache entries
      23             :    (typically only zero or one, in rare cases where the program content
      24             :    differs across forks multiple).
      25             : 
      26             :    A cache entry is a progcache_rec object.  Records are partitioned by
      27             :    size class and double as value slots: an executable entry's program
      28             :    data lives in its own class's arena slot (see fd_progcache.h).
      29             : 
      30             :    ### Cache fill policy
      31             : 
      32             :    fd_progcache is lazily filled on reads.  Writes do not invalidate
      33             :    the cache; coherence comes from keying records on deploy_slot plus
      34             :    fork cancel, and from the BPF loader's pd_write gate failing an
      35             :    invoke before fd_progcache_pull if the programdata was superseded
      36             :    this slot.
      37             : 
      38             :    ### Cache evict policy
      39             : 
      40             :    Cache eviction (i.e. force removal of potentially useful records)
      41             :    happens on fill: when a fill finds its size class full, it evicts
      42             :    within that class (per-class CLOCK), and falls back to the spill
      43             :    scratch if no record frees up.  The accdb tile's housekeeping runs
      44             :    the same sweep to keep a few slots free per class.
      45             : 
      46             :    ### Garbage collect policy
      47             : 
      48             :    When a database fork is cancelled (a competing history dies, or the
      49             :    consensus layer prunes a fork), its records are unmapped at once and
      50             :    their slots recovered by the next sweep.  A superseded revision stays
      51             :    mapped until CLOCK evicts it. */
      52             : 
      53             : #include "fd_progcache.h"
      54             : #include "fd_prog_load.h"
      55             : #include "fd_progcache_lineage.h"
      56             : #include "../runtime/fd_runtime_const.h"
      57             : 
      58             : struct fd_progcache_metrics {
      59             :   ulong lookup_cnt;
      60             :   ulong hit_cnt;
      61             :   ulong miss_cnt;
      62             :   ulong hit_loading_cnt;
      63             :   ulong class_full_cnt;
      64             :   ulong fill_cnt;
      65             :   ulong fill_tot_sz;
      66             :   ulong spill_cnt;
      67             :   ulong spill_tot_sz;
      68             :   ulong evict_cnt;
      69             :   ulong evict_tot_sz;
      70             :   ulong cum_pull_ticks;
      71             :   ulong load_cnt;
      72             :   ulong cum_load_ticks;
      73             :   /* Per-size-class breakdowns. */
      74             :   ulong hit_per_class  [ FD_PROGCACHE_CACHE_CLASS_CNT ];
      75             :   ulong fill_per_class [ FD_PROGCACHE_CACHE_CLASS_CNT ];
      76             :   ulong evict_per_class[ FD_PROGCACHE_CACHE_CLASS_CNT ];
      77             :   ulong spill_per_class[ FD_PROGCACHE_CACHE_CLASS_CNT ];
      78             : };
      79             : 
      80             : 
      81             : /* fd_progcache_t is a thread-local client to a program cache instance.
      82             :    This struct is quite large and therefore not local/stack
      83             :    declaration-friendly. */
      84             : 
      85             : struct fd_progcache {
      86             :   fd_progcache_join_t join[1];
      87             :   fd_progcache_lineage_t lineage[1];
      88             : 
      89             :   fd_progcache_metrics_t * metrics;
      90             : 
      91             :   uchar * scratch;
      92             :   ulong   scratch_sz;
      93             : 
      94             :   uint spill_active;
      95             : };
      96             : 
      97             : /* Writes every progcache counter for a tile. */
      98             : 
      99           0 : #define FD_PROGCACHE_METRICS_WRITE( TILE, m ) do {                                          \
     100           0 :     fd_progcache_metrics_t const * _m = (m);                                                \
     101           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_LOOKED_UP,                _m->lookup_cnt      );     \
     102           0 :     FD_MCNT_ENUM_COPY( TILE, PROGCACHE_HIT,                      _m->hit_per_class   );     \
     103           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_MISS,                     _m->miss_cnt        );     \
     104           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_WAITED,                   _m->hit_loading_cnt );     \
     105           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_INSERT_RETRIED,           _m->class_full_cnt  );     \
     106           0 :     FD_MCNT_ENUM_COPY( TILE, PROGCACHE_INSERTED,                 _m->fill_per_class  );     \
     107           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_INSERTED_BYTES,           _m->fill_tot_sz     );     \
     108           0 :     FD_MCNT_ENUM_COPY( TILE, PROGCACHE_SPILLED,                  _m->spill_per_class );     \
     109           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_SPILLED_BYTES,            _m->spill_tot_sz    );     \
     110           0 :     FD_MCNT_ENUM_COPY( TILE, PROGCACHE_EVICTED,                  _m->evict_per_class );     \
     111           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_EVICTED_BYTES,            _m->evict_tot_sz    );     \
     112           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_DURATION_NANOS,           _m->cum_pull_ticks  );     \
     113           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_LOADED,                   _m->load_cnt        );     \
     114           0 :     FD_MCNT_SET      ( TILE, PROGCACHE_LOAD_DURATION_NANOS,      _m->cum_load_ticks  );     \
     115           0 :   } while(0)
     116             : 
     117             : FD_PROTOTYPES_BEGIN
     118             : 
     119             : extern FD_TL fd_progcache_metrics_t fd_progcache_metrics_default;
     120             : 
     121             : /* Constructor */
     122             : 
     123             : /* fd_progcache_join joins the caller to a program cache shmem instance.
     124             :    scratch points to a FD_PROGCACHE_SCRATCH_ALIGN aligned scratch buffer
     125             :    and scratch_sz is the size of the largest program/ELF binary that is
     126             :    going to be loaded (typically max account data sz). */
     127             : 
     128             : fd_progcache_t *
     129             : fd_progcache_join( fd_progcache_t *       ljoin,
     130             :                    fd_progcache_shmem_t * shmem,
     131             :                    uchar *                scratch,
     132             :                    ulong                  scratch_sz );
     133             : 
     134          12 : #define FD_PROGCACHE_SCRATCH_ALIGN     (64UL)
     135          12 : #define FD_PROGCACHE_SCRATCH_FOOTPRINT FD_RUNTIME_ACC_SZ_MAX
     136             : 
     137             : /* fd_progcache_leave detaches the caller from a program cache. */
     138             : 
     139             : void *
     140             : fd_progcache_leave( fd_progcache_t *        cache,
     141             :                     fd_progcache_shmem_t ** opt_shmem );
     142             : 
     143             : /* fd_progcache_pull loads a program from cache, filling the cache if
     144             :    necessary.  The load operation can have a number of outcomes:
     145             :    - Returns a pointer to an existing cache entry (cache hit, state
     146             :      either "Loaded" or "FailedVerification")
     147             :    - Returns a pointer to a newly created cache entry (cache fill,
     148             :      state either "Loaded" or "FailedVerification")
     149             :    - Returns NULL if fd_prog_info rejects the account (not a deployed
     150             :      program of a known loader)
     151             :    In other words, this method guarantees to return a cache entry if a
     152             :    deployed program was found in the account database, and the program
     153             :    either loaded successfully, or failed ELF/bytecode verification.
     154             :    It is the caller's responsibility to release the returned record with
     155             :    fd_progcache_rec_close. */
     156             : 
     157             : fd_progcache_rec_t * /* read locked */
     158             : fd_progcache_pull( fd_progcache_t *           cache,
     159             :                    fd_progcache_fork_id_t     fork_id,
     160             :                    fd_pubkey_t const *        prog_addr,
     161             :                    fd_prog_load_env_t const * env,
     162             :                    fd_acc_t const *           progdata_ro );
     163             : 
     164             : /* fd_progcache_rec_close releases a cache record handle returned by
     165             :    fd_progcache_pull. */
     166             : 
     167             : void
     168             : fd_progcache_rec_close( fd_progcache_t *     cache,
     169             :                         fd_progcache_rec_t * rec );
     170             : 
     171             : FD_PROTOTYPES_END
     172             : 
     173             : #endif /* HEADER_fd_src_flamenco_progcache_fd_progcache_user_h */

Generated by: LCOV version 1.14