Line data Source code
1 : /* The backtest command spawns a smaller topology for replaying shreds from
2 : rocksdb (or other sources TBD) and reproduce the behavior of replay tile.
3 :
4 : The smaller topology is:
5 : repair_repla replay_exec exec_writer
6 : backtest-------------->replay------------->exec------------->writer
7 : ^ |^ | | ^
8 : |____________________|| | |___________________________________|
9 : replay_out | |
10 : | |------------------------------>no consumer
11 : no producer------------- stake_out, send_out, poh_out
12 : store_replay
13 :
14 : */
15 :
16 : #include "../../firedancer/topology.h"
17 : #include "../../shared/commands/configure/configure.h"
18 : #include "../../shared/commands/run/run.h" /* initialize_workspaces */
19 : #include "../../shared/fd_config.h" /* config_t */
20 : #include "../../platform/fd_sys_util.h"
21 : #include "../../../disco/tiles.h"
22 : #include "../../../disco/topo/fd_topob.h"
23 : #include "../../../disco/metrics/fd_metrics.h"
24 : #include "../../../util/pod/fd_pod_format.h"
25 : #include "../../../discof/replay/fd_replay_tile.h"
26 : #include "../../../discof/restore/utils/fd_ssmsg.h"
27 : #include "../../../discof/tower/fd_tower_tile.h"
28 : #include "../../../discof/reasm/fd_reasm.h"
29 : #include "../../../discof/replay/fd_exec.h" /* FD_RUNTIME_PUBLIC_ACCOUNT_UPDATE_MSG_MTU */
30 :
31 : #include "../main.h"
32 :
33 : #include <unistd.h> /* pause */
34 :
35 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
36 : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
37 :
38 : static void
39 0 : backtest_topo( config_t * config ) {
40 0 : ulong exec_tile_cnt = config->firedancer.layout.exec_tile_count;
41 0 : ulong writer_tile_cnt = config->firedancer.layout.writer_tile_count;
42 :
43 0 : int disable_snap_loader = !config->gossip.entrypoints_cnt;
44 0 : int solcap_enabled = strlen( config->capture.solcap_capture )>0;
45 :
46 0 : fd_topo_t * topo = { fd_topob_new( &config->topo, config->name ) };
47 0 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
48 0 : topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
49 :
50 0 : ulong cpu_idx = 0;
51 :
52 0 : fd_topob_wksp( topo, "metric_in" );
53 :
54 : /**********************************************************************/
55 : /* Add the backtest tile to topo */
56 : /**********************************************************************/
57 0 : fd_topob_wksp( topo, "back" );
58 0 : fd_topo_tile_t * backtest_tile = fd_topob_tile( topo, "back", "back", "metric_in", cpu_idx++, 0, 0 );
59 :
60 : /**********************************************************************/
61 : /* Add the replay tile to topo */
62 : /**********************************************************************/
63 0 : fd_topob_wksp( topo, "replay" );
64 0 : fd_topo_tile_t * replay_tile = fd_topob_tile( topo, "replay", "replay", "metric_in", cpu_idx++, 0, 0 );
65 :
66 : /* specified by [tiles.replay] */
67 :
68 0 : fd_topob_wksp( topo, "funk" );
69 0 : fd_topo_obj_t * funk_obj = setup_topo_funk( topo, "funk",
70 0 : config->firedancer.funk.max_account_records,
71 0 : config->firedancer.funk.max_database_transactions,
72 0 : config->firedancer.funk.heap_size_gib,
73 0 : config->firedancer.funk.lock_pages );
74 :
75 0 : fd_topob_tile_uses( topo, replay_tile, funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
76 :
77 : /**********************************************************************/
78 : /* Add the executor tiles to topo */
79 : /**********************************************************************/
80 0 : fd_topob_wksp( topo, "exec" );
81 0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
82 0 : FOR(exec_tile_cnt) fd_topob_tile( topo, "exec", "exec", "metric_in", cpu_idx++, 0, 0 );
83 :
84 : /**********************************************************************/
85 : /* Add the writer tiles to topo */
86 : /**********************************************************************/
87 0 : fd_topob_wksp( topo, "writer" );
88 0 : FOR(writer_tile_cnt) fd_topob_tile( topo, "writer", "writer", "metric_in", cpu_idx++, 0, 0 );
89 :
90 : /**********************************************************************/
91 : /* Add the snapshot tiles to topo */
92 : /**********************************************************************/
93 0 : fd_topo_tile_t * snapin_tile = NULL;
94 0 : if( FD_UNLIKELY( !disable_snap_loader ) ) {
95 0 : fd_topob_wksp( topo, "snaprd" );
96 0 : fd_topob_wksp( topo, "snapdc" );
97 0 : fd_topob_wksp( topo, "snapin" );
98 0 : fd_topo_tile_t * snaprd_tile = fd_topob_tile( topo, "snaprd", "snaprd", "metric_in", cpu_idx++, 0, 0 );
99 0 : fd_topo_tile_t * snapdc_tile = fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", cpu_idx++, 0, 0 );
100 0 : snapin_tile = fd_topob_tile( topo, "snapin", "snapin", "metric_in", cpu_idx++, 0, 0 );
101 0 : snaprd_tile->allow_shutdown = 1;
102 0 : snapdc_tile->allow_shutdown = 1;
103 0 : snapin_tile->allow_shutdown = 1;
104 0 : } else {
105 0 : fd_topob_wksp( topo, "genesi" );
106 0 : fd_topob_tile( topo, "genesi", "genesi", "metric_in", cpu_idx++, 0, 0 )->allow_shutdown = 1;
107 0 : }
108 :
109 : /**********************************************************************/
110 : /* Setup backtest->replay link (repair_repla) in topo */
111 : /**********************************************************************/
112 :
113 : /* The repair tile is replaced by the backtest tile for the repair to
114 : replay link. The frag interface is a "slice", ie. entry batch,
115 : which is provided by the backtest tile, which reads in the entry
116 : batches from the CLI-specified source (eg. RocksDB). */
117 :
118 0 : fd_topob_wksp( topo, "repair_repla" );
119 0 : fd_topob_link( topo, "repair_repla", "repair_repla", 65536UL, sizeof(fd_reasm_fec_t), 1UL );
120 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "repair_repla", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
121 0 : fd_topob_tile_out( topo, "back", 0UL, "repair_repla", 0UL );
122 :
123 : /**********************************************************************/
124 : /* Setup snapshot links in topo */
125 : /**********************************************************************/
126 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
127 0 : fd_topob_wksp( topo, "snap_zstd" );
128 0 : fd_topob_wksp( topo, "snap_stream");
129 0 : fd_topob_wksp( topo, "snapdc_rd" );
130 0 : fd_topob_wksp( topo, "snapin_rd" );
131 0 : fd_topob_wksp( topo, "snap_out" );
132 0 : fd_topob_wksp( topo, "replay_manif" );
133 : /* TODO: Should be depth of 1 or 2, not 4, but it causes backpressure
134 : from the replay tile parsing the manifest, remove when this is
135 : fixed. */
136 0 : fd_topob_link( topo, "snap_out", "snap_out", 4UL, sizeof(fd_snapshot_manifest_t), 1UL );
137 :
138 0 : fd_topob_link( topo, "snap_zstd", "snap_zstd", 8192UL, 16384UL, 1UL );
139 0 : fd_topob_link( topo, "snap_stream", "snap_stream", 2048UL, USHORT_MAX, 1UL );
140 0 : fd_topob_link( topo, "snapdc_rd", "snapdc_rd", 128UL, 0UL, 1UL );
141 0 : fd_topob_link( topo, "snapin_rd", "snapin_rd", 128UL, 0UL, 1UL );
142 :
143 0 : fd_topob_tile_out( topo, "snaprd", 0UL, "snap_zstd", 0UL );
144 0 : fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in", "snap_zstd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
145 0 : fd_topob_tile_out( topo, "snapdc", 0UL, "snap_stream", 0UL );
146 0 : fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snap_stream", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
147 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snap_out", 0UL );
148 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snap_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
149 :
150 0 : fd_topob_tile_in( topo, "snaprd", 0UL, "metric_in", "snapdc_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
151 0 : fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_rd", 0UL );
152 0 : fd_topob_tile_in( topo, "snaprd", 0UL, "metric_in", "snapin_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
153 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_rd", 0UL );
154 0 : } else {
155 0 : fd_topob_wksp( topo, "genesi_out" );
156 0 : fd_topob_link( topo, "genesi_out", "genesi_out", 2UL, 10UL*1024UL*1024UL+32UL+sizeof(fd_lthash_value_t), 1UL );
157 0 : fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
158 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
159 0 : }
160 :
161 : /**********************************************************************/
162 : /* More backtest->replay links in topo */
163 : /**********************************************************************/
164 :
165 : /* The tower tile is replaced by the backtest tile for the tower to
166 : replay link. The backtest tile simply sends monotonically
167 : increasing rooted slot numbers to the replay tile, once after each
168 : "replayed a full slot" notification received from the replay tile.
169 : This allows the replay tile to advance its watermark, and publish
170 : various data structures. This is an oversimplified barebones mock
171 : of the tower tile. */
172 0 : fd_topob_wksp( topo, "tower_out" );
173 0 : fd_topob_link( topo, "tower_out", "tower_out", 2UL, sizeof(fd_tower_slot_done_t), 1UL );
174 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
175 0 : fd_topob_tile_out( topo, "back", 0UL, "tower_out", 0UL );
176 :
177 : /**********************************************************************/
178 : /* Setup replay->stake/send/poh links in topo w/o consumers */
179 : /**********************************************************************/
180 0 : fd_topob_wksp( topo, "replay_stake" );
181 0 : fd_topob_wksp( topo, "replay_poh" );
182 :
183 0 : fd_topob_link( topo, "replay_stake", "replay_stake", 128UL, 40UL + 40200UL * 40UL, 1UL );
184 0 : ulong bank_tile_cnt = config->layout.bank_tile_count;
185 0 : FOR(bank_tile_cnt) fd_topob_link( topo, "replay_poh", "replay_poh", 128UL, (4096UL*sizeof(fd_txn_p_t))+sizeof(fd_microblock_trailer_t), 1UL );
186 :
187 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_stake", 0UL );
188 0 : FOR(bank_tile_cnt) fd_topob_tile_out( topo, "replay", 0UL, "replay_poh", i );
189 :
190 0 : topo->links[ replay_tile->out_link_id[ fd_topo_find_tile_out_link( topo, replay_tile, "replay_stake", 0 ) ] ].permit_no_consumers = 1;
191 0 : FOR(bank_tile_cnt) topo->links[ replay_tile->out_link_id[ fd_topo_find_tile_out_link( topo, replay_tile, "replay_poh", i ) ] ].permit_no_consumers = 1;
192 :
193 : /**********************************************************************/
194 : /* Setup replay->backtest link (replay_notif) in topo */
195 : /**********************************************************************/
196 :
197 0 : fd_topob_wksp( topo, "replay_out" );
198 0 : fd_topob_link( topo, "replay_out", "replay_out", 8192UL, sizeof( fd_replay_message_t ), 1UL );
199 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
200 0 : fd_topob_tile_in ( topo, "back", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
201 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
202 0 : fd_topob_tile_in ( topo, "back", 0UL, "metric_in", "snap_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
203 0 : }
204 :
205 : /**********************************************************************/
206 : /* Setup replay->exec links in topo */
207 : /**********************************************************************/
208 0 : fd_topob_wksp( topo, "replay_exec" );
209 0 : for( ulong i=0; i<exec_tile_cnt; i++ ) {
210 0 : fd_topob_link( topo, "replay_exec", "replay_exec", 128UL, 10240UL, exec_tile_cnt );
211 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_exec", i );
212 0 : fd_topob_tile_in( topo, "exec", i, "metric_in", "replay_exec", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
213 0 : }
214 :
215 : /**********************************************************************/
216 : /* Setup exec->writer links in topo */
217 : /**********************************************************************/
218 0 : fd_topob_wksp( topo, "exec_writer" );
219 0 : FOR(exec_tile_cnt) fd_topob_link( topo, "exec_writer", "exec_writer", 128UL, FD_EXEC_WRITER_MTU, 1UL );
220 0 : FOR(exec_tile_cnt) fd_topob_tile_out( topo, "exec", i, "exec_writer", i );
221 0 : FOR(writer_tile_cnt) for( ulong j=0UL; j<exec_tile_cnt; j++ )
222 0 : fd_topob_tile_in( topo, "writer", i, "metric_in", "exec_writer", j, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
223 :
224 : /**********************************************************************/
225 : /* Setup writer->replay links in topo, to send solcap account updates
226 : so that they are serialized, and to notify replay tile that a txn
227 : has been finalized by the writer tile. */
228 : /**********************************************************************/
229 0 : fd_topob_wksp( topo, "writ_repl" );
230 0 : FOR(writer_tile_cnt) fd_topob_link( topo, "writ_repl", "writ_repl", 16384UL, sizeof(fd_writer_replay_txn_finalized_msg_t), 1UL );
231 0 : FOR(writer_tile_cnt) fd_topob_tile_out( topo, "writer", i, "writ_repl", i );
232 0 : FOR(writer_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "writ_repl", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
233 :
234 0 : if( FD_UNLIKELY( solcap_enabled ) ) {
235 : /* Capture account updates, whose updates must be centralized in the replay tile as solcap is currently not thread-safe.
236 : TODO: remove this when solcap v2 is here. */
237 0 : fd_topob_wksp( topo, "capt_replay" );
238 0 : FOR(writer_tile_cnt) fd_topob_link( topo, "capt_replay", "capt_replay", FD_CAPTURE_CTX_MAX_ACCOUNT_UPDATES, FD_CAPTURE_CTX_ACCOUNT_UPDATE_MSG_FOOTPRINT, 1UL );
239 0 : FOR(writer_tile_cnt) fd_topob_tile_out( topo, "writer", i, "capt_replay", i );
240 0 : FOR(writer_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "capt_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
241 0 : }
242 :
243 : /**********************************************************************/
244 : /* Setup the shared objs used by replay and exec tiles */
245 : /**********************************************************************/
246 :
247 0 : fd_topob_wksp( topo, "store" );
248 0 : fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", config->firedancer.store.max_completed_shred_sets, 1 );
249 0 : fd_topob_tile_uses( topo, backtest_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
250 0 : fd_topob_tile_uses( topo, replay_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
251 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
252 :
253 : /* banks_obj shared by replay, exec and writer tiles */
254 0 : fd_topob_wksp( topo, "banks" );
255 0 : fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_total_banks, config->firedancer.runtime.max_fork_width );
256 0 : fd_topob_tile_uses( topo, replay_tile, banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
257 0 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
258 0 : FOR(writer_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "writer", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
259 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
260 :
261 : /* bank_hash_cmp_obj shared by replay, exec and writer tiles */
262 0 : fd_topob_wksp( topo, "bh_cmp" );
263 0 : fd_topo_obj_t * bank_hash_cmp_obj = setup_topo_bank_hash_cmp( topo, "bh_cmp" );
264 0 : fd_topob_tile_uses( topo, replay_tile, bank_hash_cmp_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
265 0 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], bank_hash_cmp_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
266 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, bank_hash_cmp_obj->id, "bh_cmp" ) );
267 :
268 : /* exec_spad_obj shared by replay, exec and writer tiles */
269 0 : fd_topob_wksp( topo, "exec_spad" );
270 0 : for( ulong i=0UL; i<exec_tile_cnt; i++ ) {
271 0 : fd_topo_obj_t * exec_spad_obj = fd_topob_obj( topo, "exec_spad", "exec_spad" );
272 0 : fd_topob_tile_uses( topo, replay_tile, exec_spad_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
273 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], exec_spad_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
274 0 : for( ulong j=0UL; j<writer_tile_cnt; j++ ) {
275 : /* For txn_ctx. */
276 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "writer", j ) ], exec_spad_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
277 0 : }
278 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, exec_spad_obj->id, "exec_spad.%lu", i ) );
279 0 : }
280 :
281 : /* writer_fseq_obj shared by replay and writer tiles */
282 0 : fd_topob_wksp( topo, "writer_fseq" );
283 0 : for( ulong i=0UL; i<writer_tile_cnt; i++ ) {
284 0 : fd_topo_obj_t * writer_fseq_obj = fd_topob_obj( topo, "fseq", "writer_fseq" );
285 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "writer", i ) ], writer_fseq_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
286 0 : fd_topob_tile_uses( topo, replay_tile, writer_fseq_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
287 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, writer_fseq_obj->id, "writer_fseq.%lu", i ) );
288 0 : }
289 :
290 : /* txncache_obj, busy_obj and poh_slot_obj only by replay tile */
291 0 : fd_topob_wksp( topo, "tcache" );
292 0 : fd_topob_wksp( topo, "bank_busy" );
293 0 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "tcache",
294 0 : config->firedancer.runtime.max_rooted_slots,
295 0 : config->firedancer.runtime.max_live_slots,
296 0 : config->firedancer.runtime.max_transactions_per_slot );
297 0 : fd_topob_tile_uses( topo, replay_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
298 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
299 0 : for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
300 0 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
301 0 : fd_topob_tile_uses( topo, replay_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
302 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
303 0 : }
304 :
305 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
306 : /* Replay decoded manifest dcache topo obj */
307 0 : fd_topo_obj_t * replay_manifest_dcache = fd_topob_obj( topo, "dcache", "replay_manif" );
308 0 : fd_pod_insertf_ulong( topo->props, 2UL << 30UL, "obj.%lu.data_sz", replay_manifest_dcache->id );
309 0 : fd_pod_insert_ulong( topo->props, "manifest_dcache", replay_manifest_dcache->id );
310 :
311 0 : fd_topob_tile_uses( topo, snapin_tile, funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
312 0 : fd_topob_tile_uses( topo, snapin_tile, replay_manifest_dcache, FD_SHMEM_JOIN_MODE_READ_WRITE );
313 0 : fd_topob_tile_uses( topo, replay_tile, replay_manifest_dcache, FD_SHMEM_JOIN_MODE_READ_ONLY );
314 0 : }
315 :
316 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
317 0 : fd_topo_tile_t * tile = &topo->tiles[ i ];
318 0 : fd_topo_configure_tile( tile, config );
319 :
320 : /* Override */
321 0 : if( !strcmp( tile->name, "replay" ) ) {
322 0 : tile->replay.bootstrap = !config->gossip.entrypoints_cnt;
323 :
324 0 : tile->replay.enable_bank_hash_cmp = 0;
325 0 : tile->replay.enable_features_cnt = config->tiles.replay.enable_features_cnt;
326 0 : for( ulong i = 0; i < tile->replay.enable_features_cnt; i++ ) {
327 0 : strncpy( tile->replay.enable_features[i], config->tiles.replay.enable_features[i], sizeof(tile->replay.enable_features[i]) );
328 0 : }
329 0 : }
330 0 : }
331 :
332 : /**********************************************************************/
333 : /* Finish and print out the topo information */
334 : /**********************************************************************/
335 0 : fd_topob_finish( topo, CALLBACKS );
336 0 : }
337 :
338 : extern int * fd_log_private_shared_lock;
339 :
340 : static void
341 0 : backtest_cmd_topo( config_t * config ) {
342 0 : backtest_topo( config );
343 0 : }
344 :
345 : static args_t
346 0 : configure_args( void ) {
347 0 : args_t args = {
348 0 : .configure.command = CONFIGURE_CMD_INIT,
349 0 : };
350 :
351 0 : ulong stage_idx = 0UL;
352 0 : args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
353 0 : args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_normalpage;
354 0 : args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_snapshots;
355 0 : args.configure.stages[ stage_idx++ ] = NULL;
356 :
357 0 : return args;
358 0 : }
359 :
360 : void
361 : backtest_cmd_perm( args_t * args FD_PARAM_UNUSED,
362 : fd_cap_chk_t * chk,
363 0 : config_t const * config ) {
364 0 : args_t c_args = configure_args();
365 0 : configure_cmd_perm( &c_args, chk, config );
366 0 : run_cmd_perm( NULL, chk, config );
367 0 : }
368 :
369 : static void
370 : backtest_cmd_fn( args_t * args FD_PARAM_UNUSED,
371 0 : config_t * config ) {
372 0 : args_t c_args = configure_args();
373 0 : configure_cmd_fn( &c_args, config );
374 :
375 0 : run_firedancer_init( config, 1, 0 );
376 :
377 0 : fd_log_private_shared_lock[ 1 ] = 0;
378 0 : fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE );
379 0 : fd_topo_fill( &config->topo );
380 :
381 0 : double tick_per_ns = fd_tempo_tick_per_ns( NULL );
382 0 : double ns_per_tick = 1.0/tick_per_ns;
383 :
384 0 : long start = fd_log_wallclock();
385 0 : fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
386 :
387 0 : fd_topo_t * topo = &config->topo;
388 0 : int disable_snap_loader = !config->gossip.entrypoints_cnt;
389 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
390 0 : fd_topo_tile_t * snaprd_tile = &topo->tiles[ fd_topo_find_tile( topo, "snaprd", 0UL ) ];
391 0 : fd_topo_tile_t * snapdc_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapdc", 0UL ) ];
392 0 : fd_topo_tile_t * snapin_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ];
393 :
394 0 : ulong volatile * const snaprd_metrics = fd_metrics_tile( snaprd_tile->metrics );
395 0 : ulong volatile * const snapdc_metrics = fd_metrics_tile( snapdc_tile->metrics );
396 0 : ulong volatile * const snapin_metrics = fd_metrics_tile( snapin_tile->metrics );
397 :
398 0 : ulong total_off_old = 0UL;
399 0 : ulong snaprd_backp_old = 0UL;
400 0 : ulong snaprd_wait_old = 0UL;
401 0 : ulong snapdc_backp_old = 0UL;
402 0 : ulong snapdc_wait_old = 0UL;
403 0 : ulong snapin_backp_old = 0UL;
404 0 : ulong snapin_wait_old = 0UL;
405 0 : ulong acc_cnt_old = 0UL;
406 0 : sleep( 1 );
407 0 : puts( "-------------backp=(snaprd,snapdc,snapin) busy=(snaprd,snapdc,snapin)---------------" );
408 0 : long next = start+1000L*1000L*1000L;
409 0 : for(;;) {
410 0 : ulong snaprd_status = FD_VOLATILE_CONST( snaprd_metrics[ MIDX( GAUGE, TILE, STATUS ) ] );
411 0 : ulong snapdc_status = FD_VOLATILE_CONST( snapdc_metrics[ MIDX( GAUGE, TILE, STATUS ) ] );
412 0 : ulong snapin_status = FD_VOLATILE_CONST( snapin_metrics[ MIDX( GAUGE, TILE, STATUS ) ] );
413 :
414 0 : if( FD_UNLIKELY( snaprd_status==2UL && snapdc_status==2UL && snapin_status == 2UL ) ) break;
415 :
416 0 : long cur = fd_log_wallclock();
417 0 : if( FD_UNLIKELY( cur<next ) ) {
418 0 : long sleep_nanos = fd_long_min( 1000L*1000L, next-cur );
419 0 : FD_TEST( !fd_sys_util_nanosleep( (uint)(sleep_nanos/(1000L*1000L*1000L)), (uint)(sleep_nanos%(1000L*1000L*1000L)) ) );
420 0 : continue;
421 0 : }
422 :
423 0 : ulong total_off = snaprd_metrics[ MIDX( GAUGE, SNAPRD, FULL_BYTES_READ ) ] +
424 0 : snaprd_metrics[ MIDX( GAUGE, SNAPRD, INCREMENTAL_BYTES_READ ) ];
425 0 : ulong snaprd_backp = snaprd_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
426 0 : ulong snaprd_wait = snaprd_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG ) ] +
427 0 : snaprd_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG ) ] + snaprd_backp;
428 0 : ulong snapdc_backp = snapdc_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
429 0 : ulong snapdc_wait = snapdc_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG ) ] +
430 0 : snapdc_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG ) ] + snapdc_backp;
431 0 : ulong snapin_backp = snapin_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
432 0 : ulong snapin_wait = snapin_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_PREFRAG ) ] +
433 0 : snapin_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG ) ] + snapin_backp;
434 :
435 0 : ulong acc_cnt = snapin_metrics[ MIDX( GAUGE, SNAPIN, ACCOUNTS_INSERTED ) ];
436 0 : printf( "bw=%4.0f MB/s backp=(%3.0f%%,%3.0f%%,%3.0f%%) busy=(%3.0f%%,%3.0f%%,%3.0f%%) acc=%3.1f M/s\n",
437 0 : (double)( total_off-total_off_old )/1e6,
438 0 : ( (double)( snaprd_backp-snaprd_backp_old )*ns_per_tick )/1e7,
439 0 : ( (double)( snapdc_backp-snapdc_backp_old )*ns_per_tick )/1e7,
440 0 : ( (double)( snapin_backp-snapin_backp_old )*ns_per_tick )/1e7,
441 0 : 100-( ( (double)( snaprd_wait-snaprd_wait_old )*ns_per_tick )/1e7 ),
442 0 : 100-( ( (double)( snapdc_wait-snapdc_wait_old )*ns_per_tick )/1e7 ),
443 0 : 100-( ( (double)( snapin_wait-snapin_wait_old )*ns_per_tick )/1e7 ),
444 0 : (double)( acc_cnt-acc_cnt_old )/1e6 );
445 0 : fflush( stdout );
446 0 : total_off_old = total_off;
447 0 : snaprd_backp_old = snaprd_backp;
448 0 : snaprd_wait_old = snaprd_wait;
449 0 : snapdc_backp_old = snapdc_backp;
450 0 : snapdc_wait_old = snapdc_wait;
451 0 : snapin_backp_old = snapin_backp;
452 0 : snapin_wait_old = snapin_wait;
453 0 : acc_cnt_old = acc_cnt;
454 :
455 0 : next+=1000L*1000L*1000L;
456 0 : }
457 0 : }
458 :
459 0 : for(;;) pause();
460 0 : }
461 :
462 : action_t fd_action_backtest = {
463 : .name = "backtest",
464 : .fn = backtest_cmd_fn,
465 : .perm = backtest_cmd_perm,
466 : .topo = backtest_cmd_topo,
467 : };
|