LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_cost_tracker_store.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 175 193 90.7 %
Date: 2026-10-16 04:29:28 Functions: 18 18 100.0 %

          Line data    Source code
       1             : #include "fd_cost_tracker_store.h"
       2             : 
       3             : #include <errno.h>
       4             : #include <unistd.h>
       5             : 
       6         162 : #define FD_COST_TRACKER_STORE_MAGIC (0xF17EDA2CC057B000UL) /* FIREDANCER COST TRACKER STORE V0 */
       7             : 
       8             : /* set_t is the metadata of one fork's cost tracker.  An acquired cost
       9             :    tracker that is not cached is on disk. */
      10             : struct set {
      11             :   ushort next;
      12             :   ushort cache_idx; /* USHORT_MAX if the cost tracker is not cached */
      13             : };
      14             : typedef struct set set_t;
      15             : 
      16             : #define POOL_NAME  set_pool
      17         324 : #define POOL_T     set_t
      18             : #define POOL_IDX_T ushort
      19             : #include "../../util/tmpl/fd_pool.c"
      20             : 
      21             : /* cache_ent_t is an in-memory slot holding one cost tracker, plus the
      22             :    bookkeeping needed to pin and evict it. */
      23             : struct cache_ent {
      24             :   ulong set_idx; /* ULONG_MAX if the entry is empty */
      25             :   ulong pin_cnt;
      26             :   ulong lru;
      27             :   uchar data[ FD_COST_TRACKER_FOOTPRINT ] __attribute__((aligned(FD_COST_TRACKER_ALIGN)));
      28             : };
      29             : typedef struct cache_ent cache_ent_t;
      30             : 
      31             : struct fd_cost_tracker_store {
      32             :   ulong magic;
      33             :   ulong cache_cnt;
      34             :   int   disk_fd;
      35             :   ulong bench_max_cost_per_block;
      36             :   ulong seed;
      37             :   ulong set_off;
      38             :   ulong cache_off;
      39             :   ulong lru;
      40             : };
      41             : 
      42             : static inline set_t *
      43       36339 : sets( fd_cost_tracker_store_t const * store ) {
      44       36339 :   return fd_type_pun( (uchar *)store + store->set_off );
      45       36339 : }
      46             : 
      47             : static inline cache_ent_t *
      48       27939 : cache( fd_cost_tracker_store_t const * store ) {
      49       27939 :   return fd_type_pun( (uchar *)store + store->cache_off );
      50       27939 : }
      51             : 
      52             : static inline set_t *
      53             : set_query( fd_cost_tracker_store_t const * store,
      54       15672 :            ulong                           set_idx ) {
      55       15672 :   set_t * pool = sets( store );
      56       15672 :   FD_CHECK_CRIT( set_idx<set_pool_max( pool ), "invariant violation: invalid cost tracker set index" );
      57       15672 :   return pool + set_idx;
      58       15672 : }
      59             : 
      60             : static void
      61             : disk_read( fd_cost_tracker_store_t * store,
      62             :            void *                    dst,
      63          21 :            ulong                     set_idx ) {
      64          21 :   ulong off = set_idx * FD_COST_TRACKER_FOOTPRINT;
      65          21 :   ulong sz  = FD_COST_TRACKER_FOOTPRINT;
      66          21 :   ulong got = 0UL;
      67          42 :   while( got<sz ) {
      68          21 :     long n = pread( store->disk_fd, (uchar *)dst+got, sz-got, (long)(off+got) );
      69          21 :     if( FD_UNLIKELY( n<0L ) ) {
      70           0 :       if( FD_LIKELY( errno==EINTR ) ) continue;
      71           0 :       FD_LOG_CRIT(( "pread(cost tracker spill file, fd=%d) failed (%i-%s)", store->disk_fd, errno, fd_io_strerror( errno ) ));
      72           0 :     }
      73          21 :     if( FD_UNLIKELY( !n ) ) {
      74           0 :       FD_LOG_CRIT(( "unexpected EOF in cost tracker spill file (set=%lu offset=%lu size=%lu)", set_idx, off+got, sz-got ));
      75           0 :     }
      76          21 :     got += (ulong)n;
      77          21 :   }
      78          21 : }
      79             : 
      80             : static void
      81             : disk_write( fd_cost_tracker_store_t * store,
      82             :             void const *              src,
      83          33 :             ulong                     set_idx ) {
      84          33 :   ulong off = set_idx * FD_COST_TRACKER_FOOTPRINT;
      85          33 :   ulong sz  = FD_COST_TRACKER_FOOTPRINT;
      86          33 :   ulong put = 0UL;
      87          66 :   while( put<sz ) {
      88          33 :     long n = pwrite( store->disk_fd, (uchar const *)src+put, sz-put, (long)(off+put) );
      89          33 :     if( FD_LIKELY( n>0L ) ) {
      90          33 :       put += (ulong)n;
      91          33 :       continue;
      92          33 :     }
      93           0 :     if( FD_UNLIKELY( n<0L && errno==EINTR ) ) continue;
      94           0 :     if( FD_UNLIKELY( !n ) ) errno = EIO;
      95           0 :     FD_LOG_CRIT(( "pwrite(cost tracker spill file, fd=%d) failed (%i-%s)", store->disk_fd, errno, fd_io_strerror( errno ) ));
      96           0 :   }
      97          33 : }
      98             : 
      99             : /* cache_evict frees the least recently used unpinned cache entry for
     100             :    the cost tracker of set_idx, writing its previous cost tracker back
     101             :    to disk. */
     102             : 
     103             : static cache_ent_t *
     104             : cache_evict( fd_cost_tracker_store_t * store,
     105        7374 :              ulong                     set_idx ) {
     106        7374 :   set_t *       set = sets( store );
     107        7374 :   cache_ent_t * ent = cache( store );
     108             : 
     109        7374 :   cache_ent_t * victim = NULL;
     110       65964 :   for( ulong i=0UL; i<store->cache_cnt; i++ ) {
     111       58590 :     if( !ent[i].pin_cnt && (!victim || ent[i].lru<victim->lru) ) victim = ent+i;
     112       58590 :   }
     113        7374 :   FD_CHECK_CRIT( victim, "every cost tracker cache entry is pinned" );
     114             : 
     115        7374 :   if( victim->set_idx!=ULONG_MAX ) {
     116          33 :     disk_write( store, victim->data, victim->set_idx );
     117          33 :     set[ victim->set_idx ].cache_idx = USHORT_MAX;
     118          33 :   }
     119        7374 :   victim->set_idx          = set_idx;
     120        7374 :   set[ set_idx ].cache_idx = (ushort)( victim - ent );
     121        7374 :   return victim;
     122        7374 : }
     123             : 
     124             : static cache_ent_t *
     125             : cache_get( fd_cost_tracker_store_t * store,
     126        7158 :            ulong                     set_idx ) {
     127        7158 :   set_t * set = set_query( store, set_idx );
     128        7158 :   if( set->cache_idx!=USHORT_MAX ) return cache( store ) + set->cache_idx;
     129             : 
     130          21 :   cache_ent_t * ent = cache_evict( store, set_idx );
     131          21 :   disk_read( store, ent->data, set_idx );
     132          21 :   return ent;
     133        7158 : }
     134             : 
     135             : static cache_ent_t *
     136             : cached_ent( fd_cost_tracker_store_t const * store,
     137        7491 :             ulong                           set_idx ) {
     138        7491 :   set_t const * set = set_query( store, set_idx );
     139        7491 :   FD_CHECK_CRIT( set->cache_idx<store->cache_cnt, "invariant violation: cost tracker is not cached" );
     140        7491 :   return cache( store ) + set->cache_idx;
     141        7491 : }
     142             : 
     143             : ulong
     144        1650 : fd_cost_tracker_store_align( void ) {
     145        1650 :   return FD_COST_TRACKER_STORE_ALIGN;
     146        1650 : }
     147             : 
     148             : ulong
     149             : fd_cost_tracker_store_footprint( ulong max_live_slots,
     150         915 :                                  ulong cache_cnt ) {
     151         915 :   if( FD_UNLIKELY( !max_live_slots || max_live_slots>=USHORT_MAX || !cache_cnt ) ) return 0UL;
     152         906 :   cache_cnt = fd_ulong_min( cache_cnt, max_live_slots );
     153             : 
     154         906 :   ulong l = FD_LAYOUT_INIT;
     155         906 :   l = FD_LAYOUT_APPEND( l, FD_COST_TRACKER_STORE_ALIGN, sizeof(fd_cost_tracker_store_t)      );
     156         906 :   l = FD_LAYOUT_APPEND( l, set_pool_align(),            set_pool_footprint( max_live_slots ) );
     157         906 :   l = FD_LAYOUT_APPEND( l, alignof(cache_ent_t),        sizeof(cache_ent_t)*cache_cnt        );
     158         906 :   return FD_LAYOUT_FINI( l, FD_COST_TRACKER_STORE_ALIGN );
     159         915 : }
     160             : 
     161             : void *
     162             : fd_cost_tracker_store_new( void * shmem,
     163             :                            int    disk_fd,
     164             :                            ulong  max_live_slots,
     165             :                            ulong  cache_cnt,
     166             :                            ulong  bench_max_cost_per_block,
     167         171 :                            ulong  seed ) {
     168         171 :   if( FD_UNLIKELY( !shmem ) ) {
     169           3 :     FD_LOG_WARNING(( "NULL shmem" ));
     170           3 :     return NULL;
     171           3 :   }
     172             : 
     173         168 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_cost_tracker_store_align() ) ) ) {
     174           3 :     FD_LOG_WARNING(( "misaligned shmem" ));
     175           3 :     return NULL;
     176           3 :   }
     177             : 
     178         165 :   if( FD_UNLIKELY( disk_fd<0 ) ) {
     179           3 :     FD_LOG_WARNING(( "invalid disk_fd %d", disk_fd ));
     180           3 :     return NULL;
     181           3 :   }
     182             : 
     183         162 :   if( FD_UNLIKELY( !fd_cost_tracker_store_footprint( max_live_slots, cache_cnt ) ) ) {
     184           0 :     FD_LOG_WARNING(( "invalid max_live_slots %lu or cache_cnt %lu", max_live_slots, cache_cnt ));
     185           0 :     return NULL;
     186           0 :   }
     187             : 
     188         162 :   cache_cnt = fd_ulong_min( cache_cnt, max_live_slots );
     189             : 
     190         162 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
     191         162 :   fd_cost_tracker_store_t * store     = FD_SCRATCH_ALLOC_APPEND( l, FD_COST_TRACKER_STORE_ALIGN, sizeof(fd_cost_tracker_store_t)      );
     192         162 :   void *                    set_mem   = FD_SCRATCH_ALLOC_APPEND( l, set_pool_align(),            set_pool_footprint( max_live_slots ) );
     193         162 :   cache_ent_t *             cache_mem = FD_SCRATCH_ALLOC_APPEND( l, alignof(cache_ent_t),        sizeof(cache_ent_t)*cache_cnt        );
     194         162 :   FD_SCRATCH_ALLOC_FINI( l, FD_COST_TRACKER_STORE_ALIGN );
     195             : 
     196         162 :   set_t * set_pool = set_pool_join( set_pool_new( set_mem, max_live_slots ) );
     197         162 :   if( FD_UNLIKELY( !set_pool ) ) {
     198           0 :     FD_LOG_WARNING(( "failed to create cost tracker set pool" ));
     199           0 :     return NULL;
     200           0 :   }
     201             : 
     202         162 :   store->cache_cnt                = cache_cnt;
     203         162 :   store->disk_fd                  = disk_fd;
     204         162 :   store->bench_max_cost_per_block = bench_max_cost_per_block;
     205         162 :   store->seed                     = seed;
     206         162 :   store->set_off                  = (ulong)set_pool  - (ulong)store;
     207         162 :   store->cache_off                = (ulong)cache_mem - (ulong)store;
     208        1242 :   for( ulong i=0UL; i<cache_cnt; i++ ) cache_mem[ i ].pin_cnt = 0UL;
     209         162 :   fd_cost_tracker_store_reset( store );
     210             : 
     211         162 :   FD_COMPILER_MFENCE();
     212         162 :   FD_VOLATILE( store->magic ) = FD_COST_TRACKER_STORE_MAGIC;
     213         162 :   FD_COMPILER_MFENCE();
     214             : 
     215         162 :   return shmem;
     216         162 : }
     217             : 
     218             : fd_cost_tracker_store_t *
     219             : fd_cost_tracker_store_join( void * shmem,
     220         435 :                             int    disk_fd ) {
     221         435 :   fd_cost_tracker_store_t * store = shmem;
     222             : 
     223         435 :   if( FD_UNLIKELY( !store ) ) {
     224           3 :     FD_LOG_WARNING(( "NULL shmem" ));
     225           3 :     return NULL;
     226           3 :   }
     227             : 
     228         432 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)store, fd_cost_tracker_store_align() ) ) ) {
     229           3 :     FD_LOG_WARNING(( "misaligned shmem" ));
     230           3 :     return NULL;
     231           3 :   }
     232             : 
     233         429 :   if( FD_UNLIKELY( store->magic!=FD_COST_TRACKER_STORE_MAGIC ) ) {
     234           0 :     FD_LOG_WARNING(( "bad magic" ));
     235           0 :     return NULL;
     236           0 :   }
     237             : 
     238         429 :   if( FD_UNLIKELY( store->disk_fd!=disk_fd ) ) {
     239           3 :     FD_LOG_WARNING(( "disk_fd mismatch (store=%d join=%d)", store->disk_fd, disk_fd ));
     240           3 :     return NULL;
     241           3 :   }
     242             : 
     243         426 :   return store;
     244         429 : }
     245             : 
     246             : void
     247        4917 : fd_cost_tracker_store_reset( fd_cost_tracker_store_t * store ) {
     248        4917 :   set_t * pool = sets( store );
     249        4917 :   ulong   max  = set_pool_max( pool );
     250       84846 :   for( ulong i=0UL; i<max; i++ ) pool[ i ] = (set_t){ .cache_idx = USHORT_MAX };
     251        4917 :   set_pool_reset( pool );
     252        4917 :   store->lru = 0UL;
     253        4917 :   cache_ent_t * ent = cache( store );
     254       44004 :   for( ulong i=0UL; i<store->cache_cnt; i++ ) {
     255       39087 :     FD_CHECK_CRIT( !ent[i].pin_cnt, "invariant violation: resetting pinned cost tracker cache" );
     256       39087 :     ent[i].set_idx = ULONG_MAX;
     257       39087 :     ent[i].lru     = 0UL;
     258       39087 :   }
     259        4917 : }
     260             : 
     261             : ushort
     262             : fd_cost_tracker_store_new_fork( fd_cost_tracker_store_t * store,
     263        7353 :                                 ushort                    old_fork_id ) {
     264        7353 :   if( FD_LIKELY( old_fork_id!=USHORT_MAX ) ) fd_cost_tracker_store_release( store, old_fork_id );
     265             : 
     266        7353 :   set_t * pool = sets( store );
     267        7353 :   FD_CHECK_CRIT( set_pool_free( pool ), "invariant violation: no free cost tracker sets" );
     268        7353 :   ulong         set_idx = set_pool_idx_acquire( pool );
     269        7353 :   cache_ent_t * ent     = cache_evict( store, set_idx );
     270        7353 :   FD_TEST( fd_cost_tracker_join( fd_cost_tracker_new( ent->data, store->bench_max_cost_per_block, store->seed ) ) );
     271        7353 :   ent->lru = ++store->lru;
     272        7353 :   return (ushort)set_idx;
     273        7353 : }
     274             : 
     275             : void
     276             : fd_cost_tracker_store_release( fd_cost_tracker_store_t * store,
     277        1023 :                                ushort                    fork_id ) {
     278        1023 :   set_t * set = set_query( store, (ulong)fork_id );
     279        1023 :   if( set->cache_idx!=USHORT_MAX ) {
     280        1020 :     cache_ent_t * ent = cache( store ) + set->cache_idx;
     281        1020 :     FD_CHECK_CRIT( !ent->pin_cnt, "invariant violation: releasing a pinned cost tracker" );
     282        1020 :     ent->set_idx   = ULONG_MAX;
     283        1020 :     ent->lru       = 0UL;
     284        1020 :     set->cache_idx = USHORT_MAX;
     285        1020 :   }
     286        1023 :   set_pool_idx_release( sets( store ), (ulong)fork_id );
     287        1023 : }
     288             : 
     289             : fd_cost_tracker_t *
     290             : fd_cost_tracker_store_pin( fd_cost_tracker_store_t * store,
     291        7158 :                            ushort                    fork_id ) {
     292        7158 :   cache_ent_t * ent = cache_get( store, (ulong)fork_id );
     293        7158 :   ent->pin_cnt++;
     294        7158 :   ent->lru = ++store->lru;
     295        7158 :   return fd_type_pun( ent->data );
     296        7158 : }
     297             : 
     298             : void
     299             : fd_cost_tracker_store_unpin( fd_cost_tracker_store_t * store,
     300        7158 :                              ushort                    fork_id ) {
     301        7158 :   cache_ent_t * ent = cached_ent( store, (ulong)fork_id );
     302        7158 :   FD_CHECK_CRIT( ent->pin_cnt, "invariant violation: unpinning an unpinned cost tracker" );
     303        7158 :   ent->pin_cnt--;
     304        7158 : }
     305             : 
     306             : fd_cost_tracker_t *
     307             : fd_cost_tracker_store_peek( fd_cost_tracker_store_t const * store,
     308         333 :                             ushort                          fork_id ) {
     309         333 :   return fd_type_pun( cached_ent( store, (ulong)fork_id )->data );
     310         333 : }

Generated by: LCOV version 1.14