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