Line data Source code
1 : #define _GNU_SOURCE
2 : #include "fddev.h"
3 :
4 : #include "../fdctl/configure/configure.h"
5 : #include "../fdctl/run/run.h"
6 :
7 : #include "../../disco/topo/fd_topob.h"
8 : #include "../../util/shmem/fd_shmem_private.h"
9 :
10 : #include <unistd.h>
11 : #include <stdio.h>
12 : #include <sched.h>
13 : #include <fcntl.h>
14 : #include <pthread.h>
15 : #include <linux/capability.h>
16 : #include <linux/futex.h>
17 : #include <sys/syscall.h>
18 : #include <sys/wait.h>
19 : #include <sys/socket.h>
20 : #include <arpa/inet.h>
21 :
22 : #include "../../util/tile/fd_tile_private.h"
23 :
24 : void
25 : bench_cmd_perm( args_t * args,
26 : fd_caps_ctx_t * caps,
27 0 : config_t * const config ) {
28 0 : (void)args;
29 :
30 0 : args_t configure_args = {
31 0 : .configure.command = CONFIGURE_CMD_INIT,
32 0 : };
33 0 : for( ulong i=0; i<CONFIGURE_STAGE_COUNT; i++ )
34 0 : configure_args.configure.stages[ i ] = STAGES[ i ];
35 0 : configure_cmd_perm( &configure_args, caps, config );
36 :
37 0 : run_cmd_perm( NULL, caps, config );
38 0 : }
39 :
40 : void
41 : bench_cmd_args( int * pargc,
42 : char *** pargv,
43 0 : args_t * args ) {
44 0 : (void)pargc;
45 0 : (void)pargv;
46 0 : (void)args;
47 0 : args->load.no_quic = fd_env_strip_cmdline_contains( pargc, pargv, "--no-quic" );
48 0 : }
49 :
50 : static void *
51 0 : agave_thread_main( void * _args ) {
52 0 : config_t * config = _args;
53 0 : agave_boot( config );
54 :
55 : /* Agave will never exit, we never set exit flag to true */
56 0 : FD_LOG_ERR(( "agave_boot() exited" ));
57 0 : return NULL;
58 0 : }
59 :
60 : void
61 : add_bench_topo( fd_topo_t * topo,
62 : char const * affinity,
63 : ulong benchg_tile_cnt,
64 : ulong benchs_tile_cnt,
65 : ulong accounts_cnt,
66 : int transaction_mode,
67 : float contending_fraction,
68 : float cu_price_spread,
69 : ulong conn_cnt,
70 : ushort send_to_port,
71 : uint send_to_ip_addr,
72 : ushort rpc_port,
73 : uint rpc_ip_addr,
74 0 : int no_quic ) {
75 :
76 0 : fd_topob_wksp( topo, "bench" );
77 0 : fd_topob_link( topo, "bencho_out", "bench", 128UL, 64UL, 1UL );
78 0 : for( ulong i=0UL; i<benchg_tile_cnt; i++ ) fd_topob_link( topo, "benchg_s", "bench", 65536UL, FD_TXN_MTU, 1UL );
79 :
80 0 : int is_bench_auto_affinity = !strcmp( affinity, "auto" );
81 :
82 0 : ushort parsed_tile_to_cpu[ FD_TILE_MAX ];
83 0 : for( ulong i=0UL; i<FD_TILE_MAX; i++ ) parsed_tile_to_cpu[ i ] = USHORT_MAX;
84 :
85 0 : ulong affinity_tile_cnt = 0UL;
86 0 : if( FD_LIKELY( !is_bench_auto_affinity ) ) affinity_tile_cnt = fd_tile_private_cpus_parse( affinity, parsed_tile_to_cpu );
87 :
88 0 : ulong tile_to_cpu[ FD_TILE_MAX ] = {0};
89 0 : for( ulong i=0UL; i<affinity_tile_cnt; i++ ) {
90 0 : if( FD_UNLIKELY( parsed_tile_to_cpu[ i ]!=USHORT_MAX && parsed_tile_to_cpu[ i ]>=fd_numa_cpu_cnt() ) )
91 0 : FD_LOG_ERR(( "The CPU affinity string in the configuration file under [development.bench.affinity] specifies a CPU index of %hu, but the system "
92 0 : "only has %lu CPUs. You should either change the CPU allocations in the affinity string, or increase the number of CPUs "
93 0 : "in the system.",
94 0 : parsed_tile_to_cpu[ i ], fd_numa_cpu_cnt() ));
95 0 : tile_to_cpu[ i ] = fd_ulong_if( parsed_tile_to_cpu[ i ]==USHORT_MAX, ULONG_MAX, (ulong)parsed_tile_to_cpu[ i ] );
96 0 : }
97 0 : if( FD_LIKELY( !is_bench_auto_affinity ) ) {
98 0 : if( FD_UNLIKELY( affinity_tile_cnt<benchg_tile_cnt+1UL+benchs_tile_cnt ) )
99 0 : FD_LOG_ERR(( "The benchmark topology you are using has %lu bench tiles, but the CPU affinity specified "
100 0 : "in the [development.bench.affinity] only provides for %lu cores. ",
101 0 : benchg_tile_cnt+1UL+benchs_tile_cnt, affinity_tile_cnt ));
102 0 : else if( FD_UNLIKELY( affinity_tile_cnt>benchg_tile_cnt+1UL+benchs_tile_cnt ) )
103 0 : FD_LOG_WARNING(( "The benchmark topology you are using has %lu bench tiles, but the CPU affinity specified "
104 0 : "in the [development.bench.affinity] provides for %lu cores. The extra cores will be unused.",
105 0 : benchg_tile_cnt+1UL+benchs_tile_cnt, affinity_tile_cnt ));
106 0 : }
107 0 : fd_topo_tile_t * bencho = fd_topob_tile( topo, "bencho", "bench", "bench", tile_to_cpu[ 0 ], 0 );
108 0 : bencho->bencho.rpc_port = rpc_port;
109 0 : bencho->bencho.rpc_ip_addr = rpc_ip_addr;
110 0 : for( ulong i=0UL; i<benchg_tile_cnt; i++ ) {
111 0 : fd_topo_tile_t * benchg = fd_topob_tile( topo, "benchg", "bench", "bench", tile_to_cpu[ i+1UL ], 0 );
112 0 : benchg->benchg.accounts_cnt = accounts_cnt;
113 0 : benchg->benchg.mode = transaction_mode;
114 0 : benchg->benchg.contending_fraction = contending_fraction;
115 0 : benchg->benchg.cu_price_spread = cu_price_spread;
116 0 : }
117 0 : for( ulong i=0UL; i<benchs_tile_cnt; i++ ) {
118 0 : fd_topo_tile_t * benchs = fd_topob_tile( topo, "benchs", "bench", "bench", tile_to_cpu[ benchg_tile_cnt+1UL+i ], 0 );
119 0 : benchs->benchs.send_to_ip_addr = send_to_ip_addr;
120 0 : benchs->benchs.send_to_port = send_to_port;
121 0 : benchs->benchs.conn_cnt = conn_cnt;
122 0 : benchs->benchs.no_quic = no_quic;
123 0 : }
124 :
125 0 : fd_topob_tile_out( topo, "bencho", 0UL, "bencho_out", 0UL );
126 0 : for( ulong i=0UL; i<benchg_tile_cnt; i++ ) {
127 0 : fd_topob_tile_in( topo, "benchg", i, "bench", "bencho_out", 0, 1, 1 );
128 0 : fd_topob_tile_out( topo, "benchg", i, "benchg_s", i );
129 0 : }
130 0 : for( ulong i=0UL; i<benchg_tile_cnt; i++ ) {
131 0 : for( ulong j=0UL; j<benchs_tile_cnt; j++ ) {
132 0 : fd_topob_tile_in( topo, "benchs", j, "bench", "benchg_s", i, 1, 1 );
133 0 : }
134 0 : }
135 :
136 : /* This will blow away previous auto topology layouts and recompute an auto topology. */
137 0 : if( FD_UNLIKELY( is_bench_auto_affinity ) ) fd_topob_auto_layout( topo );
138 0 : fd_topob_finish( topo, fdctl_obj_align, fdctl_obj_footprint, fdctl_obj_loose );
139 0 : }
140 :
141 : extern int * fd_log_private_shared_lock;
142 :
143 : void
144 : bench_cmd_fn( args_t * args,
145 0 : config_t * const config ) {
146 0 : (void)args;
147 :
148 0 : ushort dest_port = fd_ushort_if( args->load.no_quic,
149 0 : config->tiles.quic.regular_transaction_listen_port,
150 0 : config->tiles.quic.quic_transaction_listen_port );
151 :
152 0 : config->rpc.port = fd_ushort_if( config->rpc.port, config->rpc.port, 8899 );
153 0 : config->rpc.full_api = 1;
154 :
155 0 : int is_auto_affinity = !strcmp( config->layout.affinity, "auto" );
156 0 : int is_agave_auto_affinity = !strcmp( config->layout.agave_affinity, "auto" );
157 0 : int is_bench_auto_affinity = !strcmp( config->development.bench.affinity, "auto" );
158 :
159 0 : if( FD_UNLIKELY( is_auto_affinity != is_agave_auto_affinity ||
160 0 : is_auto_affinity != is_bench_auto_affinity ) ) {
161 0 : FD_LOG_ERR(( "The CPU affinity string in the configuration file under [layout.affinity], [layout.agave_affinity], and [development.bench.affinity] must all be set to 'auto' or all be set to a specific CPU affinity string." ));
162 0 : }
163 :
164 0 : add_bench_topo( &config->topo,
165 0 : config->development.bench.affinity,
166 0 : config->development.bench.benchg_tile_count,
167 0 : config->development.bench.benchs_tile_count,
168 0 : config->development.genesis.fund_initial_accounts,
169 0 : 0, 0.0f, 0.0f,
170 0 : config->layout.quic_tile_count,
171 0 : dest_port,
172 0 : config->tiles.net.ip_addr,
173 0 : config->rpc.port,
174 0 : config->tiles.net.ip_addr,
175 0 : args->load.no_quic );
176 :
177 0 : if( FD_LIKELY( !args->dev.no_configure ) ) {
178 0 : args_t configure_args = {
179 0 : .configure.command = CONFIGURE_CMD_INIT,
180 0 : };
181 0 : for( ulong i=0; i<CONFIGURE_STAGE_COUNT; i++ )
182 0 : configure_args.configure.stages[ i ] = STAGES[ i ];
183 0 : configure_cmd_fn( &configure_args, config );
184 0 : }
185 :
186 0 : update_config_for_dev( config );
187 :
188 0 : run_firedancer_init( config, 1 );
189 :
190 0 : fd_xdp_fds_t fds = fd_topo_install_xdp( &config->topo );
191 0 : (void)fds;
192 :
193 0 : fd_log_private_shared_lock[ 1 ] = 0;
194 0 : fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE );
195 :
196 0 : fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run, NULL );
197 0 : pthread_t agave;
198 0 : pthread_create( &agave, NULL, agave_thread_main, config );
199 :
200 : /* Sleep parent thread forever, Ctrl+C will terminate. */
201 0 : for(;;) pause();
202 0 : }
|