LCOV - code coverage report
Current view: top level - app/shared_dev/commands/bench - fd_bencho.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 118 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #include "../../rpc_client/fd_rpc_client.h"
       2             : #include "../../rpc_client/fd_rpc_client_private.h"
       3             : #include "../../../../disco/topo/fd_topo.h"
       4             : #include "../../../../util/net/fd_ip4.h"
       5             : #include "../../../../discof/replay/fd_replay_tile.h"
       6             : #include "../../../../flamenco/leaders/fd_leaders.h"
       7             : 
       8             : #include <stdlib.h>
       9             : 
      10             : #define FD_BENCHO_STATE_INIT  0UL
      11           0 : #define FD_BENCHO_STATE_WAIT  1UL
      12           0 : #define FD_BENCHO_STATE_READY 2UL
      13           0 : #define FD_BENCHO_STATE_SENT  3UL
      14             : 
      15           0 : #define FD_BENCHO_RPC_INITIALIZE_TIMEOUT (30L * 1000L * 1000L * 1000L)
      16           0 : #define FD_BENCHO_RPC_RESPONSE_TIMEOUT   (5L  * 1000L * 1000L * 1000L)
      17             : 
      18             : typedef struct {
      19             :   long  rpc_ready_deadline;
      20             : 
      21             :   long  blockhash_request;
      22             :   ulong blockhash_state;
      23             :   long  blockhash_deadline;
      24             : 
      25             :   fd_rpc_client_t rpc[ 1 ];
      26             : 
      27             :   fd_wksp_t * in_mem;
      28             : 
      29             :   ulong duration_s;
      30             :   long  start_nanos;
      31             :   ulong txns;
      32             :   long  last_nanos;
      33             :   ulong slots;
      34             :   ulong max_tps;
      35             : 
      36             :   fd_wksp_t * mem;
      37             :   ulong       out_chunk0;
      38             :   ulong       out_wmark;
      39             :   ulong       out_chunk;
      40             : } fd_bencho_ctx_t;
      41             : 
      42             : FD_FN_CONST static inline ulong
      43           0 : scratch_align( void ) {
      44           0 :   return alignof(fd_bencho_ctx_t);
      45           0 : }
      46             : 
      47             : FD_FN_PURE static inline ulong
      48           0 : scratch_footprint( fd_topo_tile_t const * tile ) {
      49           0 :   (void)tile;
      50           0 :   return sizeof(fd_bencho_ctx_t);
      51           0 : }
      52             : 
      53             : static int
      54             : service_block_hash( fd_bencho_ctx_t *   ctx,
      55           0 :                     fd_stem_context_t * stem ) {
      56           0 :   int did_work = 0;
      57             : 
      58           0 :   if( FD_UNLIKELY( ctx->blockhash_state==FD_BENCHO_STATE_WAIT ) ) {
      59           0 :     if( FD_LIKELY( fd_log_wallclock()>=ctx->blockhash_deadline ) )
      60           0 :       ctx->blockhash_state = FD_BENCHO_STATE_READY;
      61           0 :   }
      62             : 
      63           0 :   if( FD_UNLIKELY( ctx->blockhash_state==FD_BENCHO_STATE_READY ) ) {
      64           0 :     ctx->blockhash_request  = fd_rpc_client_request_latest_block_hash( ctx->rpc );
      65           0 :     if( FD_UNLIKELY( ctx->blockhash_request<0L ) ) FD_LOG_ERR(( "failed to send RPC request" ));
      66             : 
      67           0 :     ctx->blockhash_state    = FD_BENCHO_STATE_SENT;
      68           0 :     ctx->blockhash_deadline = fd_log_wallclock() + FD_BENCHO_RPC_RESPONSE_TIMEOUT;
      69             : 
      70           0 :     did_work = 1;
      71           0 :   }
      72             : 
      73           0 :   if( FD_UNLIKELY( ctx->blockhash_state==FD_BENCHO_STATE_SENT ) ) {
      74           0 :     fd_rpc_client_response_t * response = fd_rpc_client_status( ctx->rpc, ctx->blockhash_request, 0 );
      75           0 :     if( FD_UNLIKELY( response->status==FD_RPC_CLIENT_PENDING ) ) {
      76           0 :       if( FD_UNLIKELY( fd_log_wallclock()>=ctx->blockhash_deadline ) ) {
      77           0 :         FD_LOG_WARNING(( "timed out waiting for RPC server to respond" ));
      78           0 :         fd_rpc_client_close( ctx->rpc, ctx->blockhash_request );
      79           0 :         ctx->blockhash_state    = FD_BENCHO_STATE_WAIT;
      80           0 :         ctx->blockhash_deadline = fd_log_wallclock() + 100L * 1000L * 1000L; /* 100 millis to retry */
      81           0 :       }
      82           0 :       return did_work;
      83           0 :     }
      84             : 
      85           0 :     if( FD_UNLIKELY( fd_log_wallclock()<ctx->rpc_ready_deadline &&
      86           0 :                      ( response->status==FD_RPC_CLIENT_ERR_NETWORK ||
      87           0 :                        response->status==FD_RPC_CLIENT_ERR_MALFORMED ) ) ) {
      88             :       /* RPC server not yet responding, give it some more time... */
      89           0 :       ctx->blockhash_state = FD_BENCHO_STATE_WAIT;
      90           0 :       ctx->blockhash_deadline = fd_log_wallclock() + 100L * 1000L * 1000L; /* 100 millis to retry */
      91           0 :       fd_rpc_client_close( ctx->rpc, ctx->blockhash_request );
      92           0 :       return did_work;
      93           0 :     }
      94             : 
      95           0 :     if( FD_UNLIKELY( response->status!=FD_RPC_CLIENT_SUCCESS ) )
      96           0 :       FD_LOG_ERR(( "RPC server returned error %ld-%s", response->status, fd_rpc_client_strerror( response->status ) ));
      97             : 
      98           0 :     ctx->blockhash_state = FD_BENCHO_STATE_WAIT;
      99           0 :     ctx->blockhash_deadline = fd_log_wallclock() + 400L * 1000L * 1000L; /* 400 millis til we fetch new blockhash */
     100           0 :     fd_memcpy( fd_chunk_to_laddr( ctx->mem, ctx->out_chunk ), response->result.latest_block_hash.block_hash, 32 );
     101           0 :     fd_stem_publish( stem, 0UL, 0UL, ctx->out_chunk, 32UL, 0UL, 0UL, 0UL );
     102           0 :     ctx->out_chunk = fd_dcache_compact_next( ctx->out_chunk, 32, ctx->out_chunk0, ctx->out_wmark );
     103             : 
     104           0 :     fd_rpc_client_close( ctx->rpc, ctx->blockhash_request );
     105             : 
     106           0 :     did_work = 1;
     107           0 :   }
     108             : 
     109           0 :   return did_work;
     110           0 : }
     111             : 
     112             : static int
     113             : returnable_frag( fd_bencho_ctx_t *   ctx,
     114             :                  ulong               in_idx,
     115             :                  ulong               seq,
     116             :                  ulong               sig,
     117             :                  ulong               chunk,
     118             :                  ulong               sz,
     119             :                  ulong               ctl,
     120             :                  ulong               tsorig,
     121             :                  ulong               tspub,
     122           0 :                  fd_stem_context_t * stem ) {
     123           0 :   (void)in_idx; (void)seq; (void)sz; (void)ctl; (void)tsorig; (void)tspub; (void)stem;
     124           0 :   if( FD_UNLIKELY( sig!=REPLAY_SIG_SLOT_COMPLETED ) ) return 0;
     125           0 :   fd_replay_slot_completed_t const * msg = fd_chunk_to_laddr_const( ctx->in_mem, chunk );
     126             : 
     127           0 :   ulong slot_txns = msg->vote_success+msg->vote_failed+msg->nonvote_success+msg->nonvote_failed;
     128           0 :   if( FD_UNLIKELY( msg->vote_success==ULONG_MAX ) ) slot_txns = 0UL;
     129           0 :   long  nanos   = msg->completion_time_nanos;
     130           0 :   long  slot_ns = nanos-ctx->last_nanos;
     131           0 :   ctx->last_nanos = nanos;
     132             : 
     133             :   /* Time whole leader windows: slot times cycle within a window */
     134           0 :   int window_end = (msg->slot%FD_EPOCH_SLOTS_PER_ROTATION)==FD_EPOCH_SLOTS_PER_ROTATION-1UL;
     135           0 :   if( FD_UNLIKELY( !ctx->start_nanos ) ) {
     136           0 :     if( FD_LIKELY( slot_txns>1UL && window_end ) ) ctx->start_nanos = nanos;
     137           0 :     return 0;
     138           0 :   }
     139           0 :   ulong tps = slot_ns>0L ? (ulong)((double)slot_txns*1e9/(double)slot_ns) : 0UL;
     140           0 :   ctx->txns += slot_txns;
     141           0 :   ctx->slots++;
     142           0 :   ctx->max_tps = fd_ulong_max( ctx->max_tps, tps );
     143           0 :   FD_LOG_INFO(( "bench slot=%lu txns=%lu dt=%.3f s tps=%lu", msg->slot, slot_txns, (double)slot_ns/1e9, tps ));
     144           0 :   if( FD_UNLIKELY( ctx->duration_s && window_end && nanos-ctx->start_nanos>=(long)ctx->duration_s*1000L*1000L*1000L ) ) {
     145           0 :     double span = (double)(nanos-ctx->start_nanos)/1e9;
     146           0 :     FD_LOG_INFO(( "BENCH_SUMMARY slots=%lu span_s=%.3f txns=%lu tps=%.0f max_slot_tps=%lu",
     147           0 :                   ctx->slots, span, ctx->txns, (double)ctx->txns/span, ctx->max_tps ));
     148           0 :     exit( 0 );
     149           0 :   }
     150           0 :   return 0;
     151           0 : }
     152             : 
     153             : static inline void
     154             : after_credit( fd_bencho_ctx_t *   ctx,
     155             :               fd_stem_context_t * stem,
     156             :               int *               opt_poll_in,
     157           0 :               int *               charge_busy ) {
     158           0 :   (void)opt_poll_in;
     159             : 
     160           0 :   int did_work_rpc                = fd_rpc_client_service( ctx->rpc, 0 );
     161           0 :   int did_work_service_block_hash = service_block_hash( ctx, stem );
     162             : 
     163           0 :   *charge_busy = did_work_rpc | did_work_service_block_hash;
     164           0 : }
     165             : 
     166             : static void
     167             : unprivileged_init( fd_topo_t const *      topo,
     168           0 :                    fd_topo_tile_t const * tile ) {
     169           0 :   fd_bencho_ctx_t * ctx = fd_topo_obj_laddr( topo, tile->tile_obj_id );
     170             : 
     171           0 :   ctx->mem        = topo->workspaces[ topo->objs[ topo->links[ tile->out_link_id[ 0 ] ].dcache_obj_id ].wksp_id ].wksp;
     172           0 :   ctx->out_chunk0 = fd_dcache_compact_chunk0( ctx->mem, topo->links[ tile->out_link_id[ 0 ] ].dcache );
     173           0 :   ctx->out_wmark  = fd_dcache_compact_wmark ( ctx->mem, topo->links[ tile->out_link_id[ 0 ] ].dcache, topo->links[ tile->out_link_id[ 0 ] ].mtu );
     174           0 :   ctx->out_chunk  = ctx->out_chunk0;
     175             : 
     176           0 :   ctx->rpc_ready_deadline = fd_log_wallclock() + FD_BENCHO_RPC_INITIALIZE_TIMEOUT;
     177           0 :   ctx->blockhash_state    = FD_BENCHO_STATE_READY;
     178           0 :   FD_LOG_NOTICE(( "connecting to RPC server " FD_IP4_ADDR_FMT ":%u", FD_IP4_ADDR_FMT_ARGS( tile->bencho.rpc_ip_addr ), tile->bencho.rpc_port ));
     179           0 :   FD_TEST( fd_rpc_client_join( fd_rpc_client_new( ctx->rpc, tile->bencho.rpc_ip_addr, tile->bencho.rpc_port ) ) );
     180             : 
     181           0 :   ctx->in_mem = NULL;
     182           0 :   if( FD_LIKELY( tile->in_cnt ) ) {   /* replay_slot, when the topology has replay */
     183           0 :     fd_topo_link_t const * link = &topo->links[ tile->in_link_id[ 0 ] ];
     184           0 :     ctx->in_mem = topo->workspaces[ topo->objs[ link->dcache_obj_id ].wksp_id ].wksp;
     185           0 :   } else if( FD_UNLIKELY( tile->bencho.duration_s ) ) {
     186           0 :     FD_LOG_ERR(( "--duration needs a replay tile" ));
     187           0 :   }
     188           0 :   ctx->duration_s  = tile->bencho.duration_s;
     189           0 :   ctx->start_nanos = 0L;
     190           0 :   ctx->txns        = 0UL;
     191           0 :   ctx->last_nanos  = 0L;
     192           0 :   ctx->slots       = 0UL;
     193           0 :   ctx->max_tps     = 0UL;
     194           0 : }
     195             : 
     196           0 : #define STEM_BURST (1UL)
     197           0 : #define STEM_CALLBACK_RETURNABLE_FRAG returnable_frag
     198             : 
     199           0 : #define STEM_CALLBACK_CONTEXT_TYPE  fd_bencho_ctx_t
     200           0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_bencho_ctx_t)
     201             : 
     202           0 : #define STEM_CALLBACK_AFTER_CREDIT after_credit
     203             : 
     204             : #include "../../../../disco/stem/fd_stem.c"
     205             : 
     206             : fd_topo_run_tile_t fd_tile_bencho = {
     207             :   .name              = "bencho",
     208             :   .scratch_align     = scratch_align,
     209             :   .scratch_footprint = scratch_footprint,
     210             :   .unprivileged_init = unprivileged_init,
     211             :   .run               = stem_run,
     212             : };

Generated by: LCOV version 1.14