LCOV - code coverage report
Current view: top level - flamenco/accdb - bench_accdb_hotread.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 27 0.0 %
Date: 2026-06-30 05:50:37 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : 
       3             : #include "fd_accdb.h"
       4             : #include "../../util/fd_util.h"
       5             : 
       6             : #include <stdlib.h>
       7             : #include <string.h>
       8             : #include <unistd.h>
       9             : #include <sys/mman.h>
      10             : 
      11             : /* bench_accdb_hotread: populate a small set of accounts so they all fit
      12             :    in cache, then hammer acquire+release read-only in a tight loop for a
      13             :    fixed duration.  This isolates the hot-path cost of in-cache reads
      14             :    without any disk I/O, eviction, or write-back noise. */
      15             : 
      16             : static uchar dummy_owner[ 32 ] = { 0xEE };
      17             : 
      18             : #define BENCH_MAX_DATA_SZ  (256UL)   /* token-account sized */
      19           0 : #define BENCH_CACHE_FOOTPRINT (16UL<<30UL)
      20             : 
      21             : static uchar data_buf[ BENCH_MAX_DATA_SZ ];
      22             : 
      23             : static void
      24             : make_pubkey( uchar pubkey[ static 32 ],
      25           0 :              ulong idx ) {
      26           0 :   fd_memset( pubkey, 0, 32UL );
      27           0 :   fd_memcpy( pubkey, &idx, sizeof(ulong) );
      28           0 : }
      29             : 
      30             : static fd_accdb_t *
      31             : bench_setup( int * out_fd,
      32             :              ulong max_accounts,
      33             :              ulong max_live_slots,
      34             :              ulong max_account_writes_per_slot,
      35             :              ulong partition_cnt,
      36           0 :              ulong partition_sz ) {
      37           0 :   int fd = memfd_create( "accdb_hotread", 0 );
      38           0 :   if( FD_UNLIKELY( fd<0 ) ) FD_LOG_ERR(( "memfd_create failed" ));
      39           0 :   *out_fd = fd;
      40             : 
      41           0 :   ulong cache_fp = BENCH_CACHE_FOOTPRINT;
      42           0 :   ulong shmem_fp = fd_accdb_shmem_footprint( max_accounts, max_live_slots, max_account_writes_per_slot, partition_cnt, cache_fp, 640UL, 1UL );
      43           0 :   FD_TEST( shmem_fp );
      44           0 :   void * shmem_mem = aligned_alloc( fd_accdb_shmem_align(), shmem_fp );
      45           0 :   FD_TEST( shmem_mem );
      46           0 :   fd_accdb_shmem_t * shmem = fd_accdb_shmem_join(
      47           0 :       fd_accdb_shmem_new( shmem_mem, max_accounts, max_live_slots,
      48           0 :                           max_account_writes_per_slot, partition_cnt,
      49           0 :                           partition_sz, cache_fp, 640UL, 0, 42UL, 1UL ) );
      50           0 :   FD_TEST( shmem );
      51             : 
      52           0 :   ulong accdb_fp = fd_accdb_footprint( max_live_slots );
      53           0 :   FD_TEST( accdb_fp );
      54           0 :   void * accdb_mem = aligned_alloc( fd_accdb_align(), accdb_fp );
      55           0 :   FD_TEST( accdb_mem );
      56           0 :   fd_accdb_t * accdb = fd_accdb_join( fd_accdb_new( accdb_mem, shmem, fd, 0UL, NULL ) );
      57           0 :   FD_TEST( accdb );
      58           0 :   return accdb;
      59           0 : }
      60             : 
      61             : int
      62             : main( int     argc,
      63             :       char ** argv ) {
      64             :   fd_boot( &argc, &argv );
      65             : 
      66             :   ulong account_cnt = fd_env_strip_cmdline_ulong( &argc, &argv, "--accounts", NULL, 10000UL );
      67             :   ulong duration_ns = fd_env_strip_cmdline_ulong( &argc, &argv, "--duration", NULL, 15000000000UL ); /* 15 s */
      68             :   uint  seed        = fd_env_strip_cmdline_uint ( &argc, &argv, "--seed",     NULL, 42U );
      69             : 
      70             :   FD_LOG_NOTICE(( "accdb hot-read bench (accounts=%lu duration=%.1f s seed=%u)",
      71             :                   account_cnt, (double)duration_ns/1e9, seed ));
      72             : 
      73             :   fd_rng_t _rng[1];
      74             :   fd_rng_t * rng = fd_rng_join( fd_rng_new( _rng, seed, 0UL ) );
      75             :   FD_TEST( rng );
      76             : 
      77             :   /* Setup */
      78             :   int fd;
      79             :   ulong partition_sz  = 1UL<<30UL;
      80             :   ulong partition_cnt = 1024UL;
      81             :   fd_accdb_t * accdb = bench_setup( &fd,
      82             :                                     account_cnt + 1024UL,
      83             :                                     64UL,
      84             :                                     (uint)account_cnt + 1024U,
      85             :                                     partition_cnt,
      86             :                                     partition_sz );
      87             : 
      88             :   fd_accdb_fork_id_t root = fd_accdb_attach_child( accdb, (fd_accdb_fork_id_t){ .val = USHORT_MAX } );
      89             :   fd_accdb_fork_id_t fork = fd_accdb_attach_child( accdb, root );
      90             : 
      91             :   /* Populate accounts so they are all in cache */
      92             :   uchar pubkey[ 32 ];
      93             :   for( ulong i=0UL; i<account_cnt; i++ ) {
      94             :     make_pubkey( pubkey, i );
      95             :     ulong sz = 165UL; /* token account */
      96             : 
      97             :     uchar const * pks[1] = { pubkey };
      98             :     int wr[1] = { 1 };
      99             :     fd_acc_t acc[1];
     100             :     memset( acc, 0, sizeof(acc) );
     101             :     fd_accdb_acquire( accdb, fork, 1UL, pks, wr, acc );
     102             :     acc[0].lamports = i+1UL;
     103             :     acc[0].data_len = sz;
     104             :     memcpy( acc[0].owner, dummy_owner, 32UL );
     105             :     memcpy( acc[0].data, data_buf, sz );
     106             :     acc[0].commit = 1;
     107             :     fd_accdb_release( accdb, 1UL, acc );
     108             :   }
     109             : 
     110             :   /* Warm: read every account once to ensure cache residency */
     111             :   for( ulong i=0UL; i<account_cnt; i++ ) {
     112             :     make_pubkey( pubkey, i );
     113             :     uchar const * pks[1] = { pubkey };
     114             :     int wr[1] = { 0 };
     115             :     fd_acc_t acc[1];
     116             :     memset( acc, 0, sizeof(acc) );
     117             :     fd_accdb_acquire( accdb, fork, 1UL, pks, wr, acc );
     118             :     fd_accdb_release( accdb, 1UL, acc );
     119             :   }
     120             : 
     121             :   FD_LOG_NOTICE(( "populated %lu accounts, starting hot read loop", account_cnt ));
     122             : 
     123             :   /* Hot loop: read-only acquire+release for duration_ns */
     124             :   ulong ops   = 0UL;
     125             :   long  start = fd_log_wallclock();
     126             :   long  stop  = start + (long)duration_ns;
     127             : 
     128             :   while( fd_log_wallclock()<stop ) {
     129             :     /* Batch of 1000 to amortize the clock call */
     130             :     for( ulong b=0UL; b<1000UL; b++ ) {
     131             :       ulong idx = fd_rng_ulong( rng ) % account_cnt;
     132             :       make_pubkey( pubkey, idx );
     133             : 
     134             :       uchar const * pks[1] = { pubkey };
     135             :       int wr[1] = { 0 };
     136             :       fd_acc_t acc[1];
     137             :       memset( acc, 0, sizeof(acc) );
     138             :       fd_accdb_acquire( accdb, fork, 1UL, pks, wr, acc );
     139             :       fd_accdb_release( accdb, 1UL, acc );
     140             :       ops++;
     141             :     }
     142             :   }
     143             : 
     144             :   long elapsed = fd_log_wallclock() - start;
     145             :   double secs  = (double)elapsed / 1e9;
     146             : 
     147             :   FD_LOG_NOTICE(( "hot-read: %lu ops in %.3f s  (%.0f ops/s, %.0f ns/op)",
     148             :                   ops, secs,
     149             :                   (double)ops / secs,
     150             :                   (double)elapsed / (double)ops ));
     151             : 
     152             :   fd_rng_delete( fd_rng_leave( rng ) );
     153             :   close( fd );
     154             : 
     155             :   FD_LOG_NOTICE(( "pass" ));
     156             :   fd_halt();
     157             :   return 0;
     158             : }

Generated by: LCOV version 1.14